【问题标题】:check if saved date is one day before to current date android检查保存日期是否比当前日期早一天 android
【发布时间】:2018-09-07 17:04:54
【问题描述】:

好的,我读到了这个:Check date with todays date

@sudocode 给出了这个代码:

Calendar c = Calendar.getInstance();

// set the calendar to start of today
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);

// and get that as a Date
Date today = c.getTime();

// or as a timestamp in milliseconds
long todayInMillis = c.getTimeInMillis();

// user-specified date which you are testing
// let's say the components come from a form or something
int year = 2011;
int month = 5;
int dayOfMonth = 20;

// reuse the calendar to set user specified date
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, dayOfMonth);

// and get that as a Date
Date dateSpecified = c.getTime();

// test your condition
if (dateSpecified.before(today)) {
  System.err.println("Date specified [" + dateSpecified + "] is before today [" + today + "]");
} else {
  System.err.println("Date specified [" + dateSpecified + "] is NOT before today [" + today + "]");
}

但是假设保存的日期是 28/01/2018 晚上 11:00,我在 28/01/2018 晚上 11:15 运行它,所以这段代码会告诉我保存的日期是之前当前日期。

我想要的是,如果保存的日期超过一天,代码应该只运行一个函数......(不是 24 小时,但实际上是一天或更早)让我们说保存日期是 27/01/2018晚上 11:00 并且当前日期是 28/01/2018 那么它应该运行.. 我该如何实现呢?

【问题讨论】:

  • 仅供参考,java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 等麻烦的旧日期时间类现在已被 java.time 类所取代。大多数 java.time 功能在 ThreeTen-Backport 项目中被反向移植到 Java 6 和 Java 7。在ThreeTenABP 项目中进一步适用于早期的Android。见How to use ThreeTenABP…

标签: android date


【解决方案1】:

你可以这样做:

public long daysBetween(Calendar first, Calendar second) {
    long diffInMillis = second.getTimeInMillis() - first.getTimeInMillis();
    return TimeUnit.MILLISECONDS.toDays(diffInMillis);
}

然后只询问差异是否 >= 1。这也假设第二个 >= 首先。

此示例使用标准 Java (7) 日期内容,因此您应该能够在您的项目中使用它。

【讨论】:

  • 太棒了!并将上一个日期存储在 SharedPreferences 中,我应该将其存储为毫秒还是其他格式?
  • 请记住,这也会产生负数 (-) 天数,因此请在 diffInMillis 之前添加一个 if 条件以避免它
【解决方案2】:

tl;博士

确定日期需要时区

仅使用 java.time,绝不使用旧版 java.util.DateCalendarjava.sql.Datejava.sql.Timestamp 等。

myResultSet.getObject( 
    … , 
    Instant.class 
)                          // Retrieve a `java.time.Instant` from a column of type akin to the SQL-standard `TIMESTAMP WITH TIME ZONE`. 
.atZone(
    ZoneId.of( "Pacific/Auckland" ) 
)
.toLocalDate()
.isEqual( 
    LocalDate.now( ZoneId.of( "Pacific/Auckland" ) )
)

避免使用旧的日期时间类

可怕的 DateCalendar 遗留类在几年前被现代 java.time 类所取代。

时区

您的问题忽略了时区的关键问题。对于任何给定的时刻,日期和时间都因时区而在全球范围内变化。不谈论时区就不能谈论日期。例如,Paris France 中午夜过后几分钟是新的一天,而 Montréal Québec 中仍然是“昨天”。

如果没有指定时区,JVM 会隐式应用其当前的默认时区。该默认值可能在运行时(!)期间change at any moment,因此您的结果可能会有所不同。最好将您的 [期望/预期时区][2] 明确指定为参数。

continent/region 的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

如果你想使用 JVM 当前的默认时区,请求它并作为参数传递。如果省略,则隐式应用 JVM 的当前默认值。最好是明确的,因为默认值可能会在任何时候在运行时被 JVM 中任何应用程序的任何线程中的任何代码更改。

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

或者指定一个日期。您可以通过数字设置月份,1 月至 12 月的编号为 1-12。

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

或者,更好的是,使用预定义的Month 枚举对象,一年中的每个月一个。提示:在整个代码库中使用这些 Month 对象,而不是仅仅使用整数,以使您的代码更具自记录性,确保有效值,并提供 type-safety

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

永远不要假设 00:00:00

此外,不要假设一天从 00:00:00 开始。由于夏令时 (DST) 等异常情况,一天可能会从另一个时间开始,例如 01:00:00。让 java.time 确定一天中的第一个时刻。指定时区以生成代表特定时刻的ZonedDateTime 对象。

ZonedDateTime startOfToday = LocalDate.now( z ).atStartOfDay( z ) ;
ZonedDateTime startOfYesterday = startOfToday.toLocalDate().minusDays( 1 ).atStartOfDay( z ) ;

对于查询数据库,通常最好使用 UTC 值。要从我们的时区调整为 UTC,只需提取 Instant

Instant start = startOfToday.toInstant() ;
Instant stop = startOfYesterday.toInstant() ;

准备好查询数据库。在此处使用半开方法,其中开始是包含,而结束是独占。所以,不要使用 SQL BETWEEN

// SQL for SELECT WHERE when_field >= ? AND when_field < ? 
myPreparedStatement.setObject( 1 , start ) ;
myPreparedStatement.setObject( 2 , stop ) ;

比较日期

如果您只想检查检索到的时刻的年龄,请检索 Instant。

Instant instant = myResultSet.getObject( … , Instant.class ) ;

应用时区以获得ZonedDateTime。然后提取仅日期值。

ZonedDateTime zdt = instant.atZone( z ) ;
LocalDate ld = zdt.toLocalDate() ;  // Extract the date-only value.

与今天的日期比较。

LocalDate yesterday = LocalDate.now( z ).minusDays( 1 ) ;  // Subtract one day from today to get yesterday.
Boolean retrievedDateIsYesterday = ld.isEqual( yesterday ) ;

如果您经常使用时间跨度,请参阅下面链接的 ThreeTen-Extra 项目中的 IntervalLocalDateRange 类。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    相关资源
    最近更新 更多