scala中两个纪元日之间的天数

时间:2017-08-01 12:10:24

标签: java scala date-difference

我有两个纪元时间戳,我试图找到两个时间戳之间的天数。

这就是我现在所拥有的:

dateFrom = inputEntry.getValue(inputFields(0).get).asInstanceOf[String].toLong
dateTo =inputEntry.getValue(inputFields(1).get).asInstanceOf[String].toLong

示例:

dateFrom    dateTo      result
1501583232  1501641000  1
1501583232  1501986600  5

我从两个纪元日期开始

2 个答案:

答案 0 :(得分:2)

TL;博士

ChronoUnit.DAYS.between( … , … )

详细

Stack Overflow已经多次介绍过这个问题。这里简要介绍......

对于日期时间值,请使用日期时间对象。仅使用java.time类,避免麻烦的遗留日期时间类(日期,日历等)。

您的意思是日期的差异或24小时的时间差异吗?

我会在这里约会。

首先,将自1970-01-01T00:00:00Z的纪元参考日期以来的整数秒数转换为UTC时间轴中的一个点。

注意数字文字末尾的L表示长而不是int。

Instant instant = Instant.ofEpochSecond( 1_501_583_232L ) ; 

指定您要考虑日期的时区。

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z );

转换为仅限日期。

LocalDate ld = zdt.toLocalDate() ;

获得好处。

long days = ChronoUnit.DAYS.between( ld , ld2 ) ;

答案 1 :(得分:1)

要获得所需的结果,您必须定义计算差异的方式。

以你的第一个例子(1501583232和1501641000之间的差异应该是1天):

纪元1501583232和1501641000是自1970-01-01T00:00Z以来的秒数,因此它们相当于以下UTC日期:

1501583232: 2017-08-01T10:27:12Z
1501641000: 2017-08-02T02:30:00Z

请注意,它们之间的差异是16小时,2分48秒(因此,不到一天)。如果你得到天数差异,从技术上讲它将为零。

但如果您认为日期(2017-08-012017-08-02)和忽略时间(小时/分钟/秒),那么差异可以是零或1,具体取决于您所在的时区。

如果您只考虑UTC日期(2017-08-012017-08-02),则差异为1天。

但如果你在America/Los_Angeles时区采用相同的UTC日期,你会得到:

1501583232: 2017-08-01T03:27:12-07:00
1501641000: 2017-08-01T19:30-07:00

现在,差异为零天,无论您是仅考虑日期(均为2017-08-01),还是日期和时间(小时数差异为16天,不到一天)。

因此,您必须定义计算差异的方式(仅考虑日期,或同时考虑日期和时间,以及将使用的时区)。

在你的情况下,似乎你只考虑日期而忽略了时间,但目前还不清楚它正在使用什么时区。无论如何,您可以使用JDK的8 new java.time API(对于JDK< = 7,您可以使用ThreeTen Backport - 下面的代码适用于两者。唯一的区别是包名称(在Java 8中是java.time和ThreeTen Backport(或Android的ThreeTenABP)是org.threeten.bp),但类和方法名称是相同的。)

代码基本上与@BasilBourque's answer相同,因为它与新API非常相似(我只想添加上面的见解)。

首先从纪元值中创建Instant

Instant instant1 = Instant.ofEpochSecond(1501583232L);
Instant instant2 = Instant.ofEpochSecond(1501641000L);

如果您想要考虑日期和时间的差异,可以使用:

ChronoUnit.DAYS.between(instant1, instant2);

结果将为零。

如果您只想考虑UTC中的日期(并忽略时间),请执行以下操作:

// convert to UTC and get just the date (day/month/year)
LocalDate d1 = instant1.atZone(ZoneOffset.UTC).toLocalDate();
LocalDate d2 = instant2.atZone(ZoneOffset.UTC).toLocalDate();
long days = ChronoUnit.DAYS.between(d1, d2);

结果将是1。

要转换为其他时区(而不是UTC),请使用ZoneId类:

// use a specific timezone
ZoneId zone = ZoneId.of("Asia/Kolkata");
// convert the Instant to a timezone and get only the date
LocalDate d1 = instant1.atZone(zone).toLocalDate();
LocalDate d2 = instant2.atZone(zone).toLocalDate();
long days = ChronoUnit.DAYS.between(d1, d2);

在这种情况下,差异为1,但正如我上面所说,不同的时区可以产生不同的结果(可以是0或1 - 例如,将上面的代码更改为ZoneId.of("America/Los_Angeles"),结果为零)。

请注意,API使用IANA timezones names(始终采用Region/City格式,如Asia/KolkataEurope/Berlin。 避免使用3个字母的缩写(例如CSTIST),因为它们是ambiguous and not standard

您可以致电ZoneId.getAvailableZoneIds()获取可用时区列表(并选择最适合您系统的时区)。

您也可以将系统的默认时区与ZoneId.systemDefault()一起使用,但即使在运行时也可以在不事先通知的情况下进行更改,因此最好明确使用特定的时区。