TL;博士
...解析...从字符串...时区未指定...我想设置一个特定的时区
LocalDateTime.parse( "2018-01-23T01:23:45.123456789" ) // Parse string, lacking an offset-from-UTC and lacking a time zone, as a `LocalDateTime`.
.atZone( ZoneId.of( "Africa/Tunis" ) ) // Assign the time zone for which you are certain this date-time was intended. Instantiates a `ZonedDateTime` object.
j.u.Date中没有时区
正如其他正确答案所述,java.util.Date没有时区†。 它代表UTC / GMT(没有时区偏移)。 非常混乱,因为它的toString方法在生成字符串表示时应用JVM的默认时区。
避免j.u.Date
出于这个原因和其他许多原因,您应该避免使用内置的java.util.Date& .Calendar&java.text.SimpleDateFormat中。 众所周知,它们很麻烦。
而是使用与Java 8捆绑在一起的java.time包。
java.time
java.time类可以通过三种方式表示时间轴上的时刻:
UTC(toString)
带偏移量(toString和ZonedDateTime)
有了时区(toString with ZonedDateTime)
toString
在java.time中,基本构建块是toString,是UTC时间线上的一个时刻。 对于您的大部分业务逻辑,请使用toString对象。
Instant instant = Instant.now();
toString
应用UTC的偏移量以调整到某个地区的挂钟时间。
申请toString获得toString。
ZoneOffset zoneOffset = ZoneOffset.of( "-04:00" );
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset );
toString
更好的是应用时区,偏移量以及处理夏令时(DST)等异常的规则。
申请toString到toString获得toString.始终指定适当的时区名称。 切勿使用诸如ZonedDateTime或IST之类的3-4缩写,既不是唯一的也不是标准化的。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
toString
如果输入字符串缺少偏移量或区域的任何指示符,则解析为toString。
如果您确定预期的时区,请指定toString以生成ZonedDateTime.请参阅上面的代码示例tl; dr部分顶部。
格式化字符串
在这三个类中的任何一个上调用toString方法,以生成表示标准ISO 8601格式的日期时间值的String。 ZonedDateTime类通过在括号中附加时区名称来扩展标准格式。
String outputInstant = instant.toString(); // Ex: 2011-12-03T10:15:30Z
String outputOdt = odt.toString(); // Ex: 2007-12-03T10:15:30+01:00
String outputZdt = zdt.toString(); // Ex: 2007-12-03T10:15:30+01:00[Europe/Paris]
对于其他格式,请使用toString类。 通常最好让该类使用用户期望的人类语言和文化规范生成本地化格式。 或者您可以指定特定格式。
关于java.time
java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,例如toString,toString,&toString。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310。
您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序。 不需要字符串,不需要toString类。
从哪里获取java.time类?
Java SE 8,Java SE 9,Java SE 10,Java SE 11及更高版本 - 带有捆绑实现的标准Java API的一部分。Java 9增加了一些小功能和修复。
Java SE 6和Java SE 7大多数java.time功能都被反向移植到Java 6& 7在ThreeTen-Backport。
Android的更高版本的Android捆绑java.time类的实现。
对于早期的Android(< 26),ThreeTenABP项目采用ThreeTen-Backport(如上所述)。 请参见如何使用ThreeTenABP ....
ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的类,例如toString,toString,toString等。
乔达时间
虽然Joda-Time仍在积极维护,但其制造商告诉我们尽快迁移到java.time。 我保留此部分作为参考,但我建议使用上面的toString部分。
在Joda-Time中,日期时间对象(toString)确实知道其指定的时区。 这意味着与UTC的偏移以及该时区的夏令时(DST)和其他此类异常的规则和历史记录。
String input = "2014-01-02T03:04:05";
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeIndia = new DateTime( input, timeZone );
DateTime dateTimeUtcGmt = dateTimeIndia.withZone( DateTimeZone.UTC );
调用toString方法以生成ISO 8601格式的String。
String output = dateTimeIndia.toString();
Joda-Time还提供丰富的功能来生成各种其他String格式。
如果需要,您可以从Joda-Time DateTime转换为java.util.Date。
Java.util.Date date = dateTimeIndia.toDate();
在“joda date”中搜索StackOverflow以查找更多示例,其中一些非常详细。
†实际上java.util.Date中嵌入了一个时区,用于某些内部函数(请参阅本答案中的注释)。 但是此内部时区不作为属性公开,并且无法设置。 此内部时区不是toString方法在生成日期时间值的字符串表示时使用的时区; 相反,JVM的当前默认时区是即时应用的。 所以,作为简写,我们经常说“j.u.Date没有时区”。混乱? 是。 避免这些疲惫的旧课程的另一个原因。