我想在今天凌晨2点设置joda DateTime
(请参阅下面的示例代码)。但我得到了这个例外:
Exception in thread "main" org.joda.time.IllegalFieldValueException: Value 2 for hourOfDay is not supported: Illegal instant due to time zone offset transition: 2011-03-27T02:52:05.239 (Europe/Prague)
at org.joda.time.chrono.ZonedChronology$ZonedDateTimeField.set(ZonedChronology.java:469)
at org.joda.time.MutableDateTime.setHourOfDay(MutableDateTime.java:702)
上述处理例外的正确方法是什么,或者在一天的特定时刻创建DateTime
?
示例代码:
MutableDateTime now = new MutableDateTime();
now.setHourOfDay(2);
now.setMinuteOfHour(0);
now.setSecondOfMinute(0);
now.setMillisOfSecond(0);
DateTime myDate = now.toDateTime();
感谢。
答案 0 :(得分:35)
您似乎正试图从特定的本地时间到DateTime
实例,并且您希望它能够抵御夏令时。试试这个...(注意我在美国/东部,所以我们的过渡日期是3月13日;我必须找到正确的日期来获得你今天获得的例外。更新了我的下面的CET代码,今天转换。这里的见解是,Joda提供LocalDateTime
让您了解当地的挂钟设置,以及它是否在您的时区合法。在这种情况下,如果时间不存在,我只需添加一小时(您的应用程序必须确定这是否是正确的策略。)
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
class TestTz {
public static void main(String[] args)
{
final DateTimeZone dtz = DateTimeZone.forID("CET");
LocalDateTime ldt = new LocalDateTime(dtz)
.withYear(2011)
.withMonthOfYear(3)
.withDayOfMonth(27)
.withHourOfDay(2);
// this is just here to illustrate I'm solving the problem;
// don't need in operational code
try {
DateTime myDateBorken = ldt.toDateTime(dtz);
} catch (IllegalArgumentException iae) {
System.out.println("Sure enough, invalid instant due to time zone offset transition!");
}
if (dtz.isLocalDateTimeGap(ldt)) {
ldt = ldt.withHourOfDay(3);
}
DateTime myDate = ldt.toDateTime(dtz);
System.out.println("No problem: "+myDate);
}
}
此代码生成:
Sure enough, invalid instant due to time zone offset transition! No problem: 2011-03-27T03:00:00.000+02:00
答案 1 :(得分:12)
CET在3月的最后一个星期天切换到夏令时(夏令时),恰好是今天。时间从1:59:59到3:00:00 - 没有2,因此例外。
您应该使用UTC而不是本地时间来避免这种时区问题。
MutableDateTime now = new MutableDateTime(DateTimeZone.UTC);
答案 2 :(得分:7)
我想很多时候,你会希望joda自动为你解决这个问题。您通常不知道修正缺口日期的正确方法,因为缺口的大小取决于区域和年份(当然通常是一小时)。
这方面的一个例子是,如果您正在解析来自您无法控制的来源的时间戳;例如,网络。如果时间戳的发件人具有过期的区域文件,则可能发生这种情况。 (如果你有过时的区域文件,你几乎搞砸了。)
这是一种做到这一点的方法,这个方法稍微复杂一些。我已经在joda 1.6以及2.x中使用它,因为我们恰好在我们的环境中陷入1.6。
如果您正在根据问题建立其他输入日期,则可以按照上面的建议开始使用UTC日期或LocalDate
,然后对其进行调整以自动修复偏移量。特殊的酱汁在DateTimeZone.convertLocalToUTC
危险:
public DateTime parse(String str) {
formatter.parseDateTime(gapdate)
}
安全:
public DateTime parse(String str) {
// separate date from zone; you may need to adjust the pattern,
// depending on what input formats you support
String[] parts = str.split("(?=[-+])");
String datepart = parts[0];
DateTimeZone zone = (parts.length == 2) ?
DateTimeZone.forID(parts[1]) : formatter.getZone();
// parsing in utc is safe, there are no gaps
// parsing a LocalDate would also be appropriate,
// but joda 1.6 doesn't support that
DateTime utc = formatter.withZone(DateTimeZone.UTC).parseDateTime(datepart);
// false means don't be strict, joda will nudge the result forward by the
// size of the gap. The method is somewhat confusingly named, we're
// actually going from UTC to local
long millis = zone.convertLocalToUTC(utc.getMillis(), false);
return new DateTime(millis, zone);
}
我在东半球和西半球以及豪勋爵岛区进行了测试,这个区恰好有半小时dst。
如果joda格式化程序支持setStrict(boolean)会让他们为你处理这个问题,那会很好...
答案 3 :(得分:4)
如果您需要从字符串解析日期:
final DateTimeZone dtz = DateTimeZone.getDefault(); //DateTimeZone.forID("Europe/Warsaw")
LocalDateTime ldt = new LocalDateTime("1946-04-14", dtz);
if (dtz.isLocalDateTimeGap(ldt)){
ldt = ldt.plusHours(1);
}
DateTime date = ldt.toDateTime();
Date date = date.toDate();
完美地为我工作。也许有人会需要它。
答案 4 :(得分:0)
更新到jodatime 2.1并使用LocalDate.parse()
:
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy");
LocalDate.parse(date, formatter);