夏令时的持续时间

时间:2017-06-18 17:48:44

标签: java timezone jodatime dst duration

我有一个对象var phrase = "an important number comes after this: 123456"; var word = "this: "; var number = phrase.substr(phrase.indexOf(word) + word.length); // number = 123456 ,其中有两个字段:ShiftstartDateTime来自Joda-Time的endDateTime

我的转变包括夏令时英国的变化。它从DateTime开始,到25/03/2017 13:00结束(基本上应该在26/03/2017 02:00结束,但此日期不存在,26/03/2017 01:00移位+1小时)。根据这个site

  

当地标准时间即将到来时   星期日,2017年3月26日,01:00:00时钟转发1小时到   2017年3月26日星期日,当地白天时间02:00:00。

现在,如果我想跟踪员工的工作小时数  endDate会给我13个小时。

如何使用Joda-Time检测夏令时是否在我的班次持续时间内开始或结束?

2 个答案:

答案 0 :(得分:2)

您可以使用org.joda.time.DateTimeZone课程。它包含有关世界上所有时区的DST更改的信息,因此您无需检测DST更改:如果您正确告知您正在使用的时区,则API会为您完成工作。

当您正在使用英国时区时,您可以直接使用Europe/London时区 - Continent/City格式的这些名称来自IANA database,而且'由Joda-Time,Java和许多其他API使用。您可以致电DateTimeZone.getAvailableIDs()来获取所有时区的列表。

当您使用DateTimeZone时,它已包含历史记录中的所有DST转换,因此API会为您完成所有数学运算。您只需要在此时区创建DateTime个实例:

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Duration;

// London timezone - it contains all info about DST shifts
DateTimeZone london = DateTimeZone.forID("Europe/London");

// Start on 25/03/2017 13:00
DateTime start = new DateTime(2017, 3, 25, 13, 0, london);
// ends on 26/03/2017 02:00
DateTime end = new DateTime(2017, 3, 26, 2, 0, london);

// get the difference between start and end
Duration duration = new Duration(start, end);
System.out.println(duration.getStandardHours()); // 12

输出结果为12(API会使用DateTime时区的信息来计算差异,包括DST转换。

您也可以使用:

duration.toStandardHours().getHours()

或者班级org.joda.time.Hours

Hours.hoursBetween(start, end).getHours()

所有人都返回12,而且他们都是等同的。

Java新日期/时间API

Joda-时间已停止并被新API取代,因此,如果您正在考虑迁移,则可以开始使用新的日期/时间API,但如果您使用的是大代码库Joda或者现在不想迁移它,你可以考虑其余的答案。

无论如何,即使在joda's website中它也说:"请注意,Joda-Time被认为是一个基本上“完成”的项目。没有计划重大改进。如果使用Java SE 8,请迁移到java.time(JSR-310)。" 。*

如果您使用 Java 8 ,请考虑使用new java.time API。它更容易,less bugged and less error-prone than the old APIs。我不确定它是否已经可用于所有Android版本(但请参阅下面的替代版本)。

如果您正在使用 Java< = 7 ,则可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。对于 Android ,可以使用ThreeTenABP(更多关于如何使用它here)来使用它。

以下代码适用于两者。 唯一的区别是包名称(在Java 8中为java.time而在ThreeTen Backport(或Android的ThreeTenABP中)为org.threeten.bp),但类和方法名称是一样的。

新API还使用IANA时区名称,并包含有关DST转换的相同历史信息(以获取所有时区列表:ZoneId.getAvailableZoneIds())。代码非常相似,并且还有不止一种方法可以解决差异:

import java.time.Duration;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;

// London timezone
ZoneId london = ZoneId.of("Europe/London");

// Start on 25/03/2017 13:00
ZonedDateTime start = ZonedDateTime.of(2017, 3, 25, 13, 0, 0, 0, london);
// ends on 26/03/2017 02:00
ZonedDateTime end = ZonedDateTime.of(2017, 3, 26, 2, 0, 0, 0, london);

// get the difference in hours
System.out.println(ChronoUnit.HOURS.between(start, end)); // 12

// get the duration in hours
Duration duration = Duration.between(start, end);
System.out.println(duration.toHours()); // 12

// using until() method
System.out.println(start.until(end, ChronoUnit.HOURS)); // 12

上述三种方法(ChronoUnit.HOURS.between()duration.toHours()start.until())都会返回12。根据{{​​3}},betweenuntil是等效的,javadoc。使用Duration也是等效的,因为它使用它们之间的纳秒并将其转换为小时。

答案 1 :(得分:0)

  1. 您应使用TimeZone ID,例如“欧洲/伦敦”
  2. 将开始时间和结束时间转换为GMT
  3. 现在从GMT开始时间和结束时间查找持续时间

当您使用TimeZone ID时,会自动处理日光。