java 使用 Joda-Time 计算持续时间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4983846/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 08:56:36  来源:igfitidea点击:

Calculating a time duration with Joda-Time

javatimezonejodatimedstleap-year

提问by bloodcell

I'm trying to use Joda-Time in order to know time durations between two points in time, where each point is given in its own local timezone.

我正在尝试使用 Joda-Time 来了解两个时间点之间的持续时间,其中每个点都在自己的本地时区中给出。

E.g. :

例如:

DateTime ny = new DateTime(2011, 2, 2, 7, 0, 0, 0, DateTimeZone.forID("America/New_York"));
DateTime la = new DateTime(2011, 2, 3, 10, 15, 0, 0, DateTimeZone.forID("America/Los_Angeles"));
DateTime utc1 = ny.withZone(DateTimeZone.UTC);
DateTime utc2 = la.withZone(DateTimeZone.UTC);        
Period period = new Period(utc1, utc2);

Now, I wish to know if this takes into account day light savings and leap years... Also, is the use of 'Period' the correct Joda-Time way to achieve this? Thanks ;)

现在,我想知道这是否考虑了夏令时和闰年......此外,使用“Period”是实现这一目标的正确 Joda-Time 方法吗?谢谢 ;)

回答by Russ Hayward

The code you provided will work and take into account time zones but you don't need to do the conversion to UTC. This code is simpler and does the same thing (using a Duration rather than a Period):

您提供的代码将起作用并考虑时区,但您不需要转换为 UTC。这段代码更简单,做同样的事情(使用 Duration 而不是 Period):

DateTime ny = new DateTime(2011, 2, 2, 7, 0, 0, 0, DateTimeZone.forID("America/New_York"));
DateTime la = new DateTime(2011, 2, 3, 10, 15, 0, 0, DateTimeZone.forID("America/Los_Angeles"));
Duration duration = new Interval(ny, la).toDuration();

回答by fcarlsen

Depending on how you use it, the code above may not be a good idea.

根据您的使用方式,上面的代码可能不是一个好主意。

All DateTime constructors that take int's for year/month/day/hour etc are vulnerable to the Daylight Savings (DST) transition periods, in which case Joda-time will throw an exception. So if the hour during transition is a possible input in your application, it will fail:

所有采用 int 表示年/月/日/小时等的 DateTime 构造函数都容易受到夏令时 (DST) 过渡期的影响,在这种情况下 Joda-time 将抛出异常。因此,如果转换期间的小时是您的应用程序中可能的输入,它将失败:

DateTime ny = new DateTime(2011, 3, 13, 2, 0, 0, 0, DateTimeZone.forID("America/New_York"));

Exception in thread "main" java.lang.IllegalArgumentException: Illegal instant due to time zone offset transition: 2011-03-13T07:00:00.000
at org.joda.time.chrono.ZonedChronology.localToUTC(ZonedChronology.java:143)
at org.joda.time.chrono.ZonedChronology.getDateTimeMillis(ZonedChronology.java:119)
at org.joda.time.chrono.AssembledChronology.getDateTimeMillis(AssembledChronology.java:133)
at org.joda.time.base.BaseDateTime.<init>(BaseDateTime.java:254)
at org.joda.time.base.BaseDateTime.<init>(BaseDateTime.java:223)
at org.joda.time.DateTime.<init>(DateTime.java:264)

Similarly, you'll face another problem in the fall, when it's not possible to determine which hour is referred to *as there will be 2 * 2o'clock in the given timezone. The DateTime methods withHourOfday and withTime are vulnerable to the same issue, as well as parsing datetimes as strings with timezones that are affected by DST.

同样,您将在秋季面临另一个问题,因为在给定的时区中将有 2 * 2 点钟,因此无法确定引用哪个小时。DateTime 方法 withHourOfday 和 withTime 容易受到同一问题的影响,并且将日期时间解析为带有受 DST 影响的时区的字符串。

Possible workarounds include

可能的解决方法包括

  • instantiating with any fixed-offset timezone instead (such as UTC)
  • parsing same as a string with a UTC timezone
  • instantiating a valid time in the local time zone (e.g. midnight) and using plusHours to move forward till the desired time
  • have a guard (if-statement) to protect against the second hour of the transition dates
  • catch the exception and check when the next transition is going to happen (using DateTimeZone.nextTransition), and move back/forward accordingly
  • 使用任何固定偏移时区进行实例化(例如 UTC)
  • 解析与 UTC 时区的字符串相同
  • 实例化本地时区的有效时间(例如午夜)并使用 plusHours 向前移动到所需时间
  • 有一个守卫(if 语句)来防止转换日期的第二个小时
  • 捕获异常并检查下一次转换何时发生(使用 DateTimeZone.nextTransition),并相应地向后/向前移动