我正在尝试使用以下代码转换MST中的当前时间
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
TimeZone toTimeZone = TimeZone.getTimeZone("MST");
sdf.setTimeZone(toTimeZone);
Date date = new Date();
String strDate = sdf.format(date.getTime());
strDate显示正确的MST时间,但解析后给出了错误的日期时间。
Date currentDate = sdf.parse(strDate);
我想要日期格式的当前MST时间,而不是字符串格式。
java.util.Date对象没有时区的概念。
- 无法为日期设置时区
- 无法更改Date对象的时区
- 使用新Date((默认构造函数创建的Date对象将使用系统默认时区中的当前时间进行初始化
您所做的只是为格式化部分添加时区信息。。。setTimeZone
不转换任何内容。
tl;dr
ZonedDateTime zdt = LocalDateTime.parse( input , DateTimeFormatter.forPattern( "dd/MM/uuuu hh:mm:ss" ) ).atZone( ZoneId.of( "America/Denver" ) );
避免使用传统日期时间类
您使用的是过时的、麻烦的遗留日期时间类。
java.time
java.time框架是在java 8及更高版本中构建的。这些类取代了诸如java.util.Date
、.Calendar
和&java.text.SimpleDateFormat
。
现在处于维护模式,JodaTime项目还建议迁移到java.Time.
要了解更多信息,请参阅Oracle教程。并在Stack Overflow中搜索许多示例和解释。
大部分java.time功能都是向后移植到Java6&ThreeTen背包中的7,并在ThreeTenABP中进一步适应Android。
ThreeTen Extra项目用额外的类扩展了java.time。这个项目是将来可能添加到java.time.的试验场
LocalDateTime
您的输入字符串没有任何与UTC或时区偏移的指示。所以我们必须解析为LocalDateTime
。LocalDateTime
没有偏移或时区,因此它不代表时间线上的某个时刻。就像说"圣诞节从12月25日午夜开始"一样,只有当你把它应用到地球上某个特定的时区时,这才有意义(只会成为时间线上的一个点(。
String input = …
DateTimeFormatter f = DateTimeFormatter.forPattern( "dd/MM/uuuu hh:mm:ss" );
LocalDateTime ldt = LocalDateTime.parse( input , f );
ZonedDateTime
如果您知道上下文并且可以假设预期的偏移量或时区,则可以分别创建OffsetDateTime
或ZonedDateTime
。
使用正确的时区名称,以continent/region
的格式命名。你所说的MST
可能是指美国落基山脉大部分地区使用的America/Denver
时区,或者加拿大部分地区使用的America/Edmonton
时区。
切勿使用3-4个字母的缩写,如MST
。这些缩写不是真正的时区,没有标准化,甚至不是唯一的(!(。
ZoneId zoneId = ZoneId.of( "America/Denver" ) ;
ZonedDateTime zdt = ldt.atZone( zoneId ) ;
转换
我建议避免使用出了名的麻烦的java.util.Date
类。但是,如果必须这样做,您可以转换到java.time类型或从java.time类型转换。要与其他代码或库进行互操作,请使用添加到旧类中的新方法进行转换。在这种情况下,使用从OffsetDateTime
或ZonedDatetime
中提取的Instant
对象并传递到java.util.Date.from
。
Instant
类表示UTC时间线上的一个时刻,分辨率为纳秒。
java.util.Date utilDate = java.util.Date.from( zdt.toInstant() ) ;
另一方面,使用添加到旧类中的另一个新方法java.util.Instant::toInstant
。
Instant instant = utilDate.toInstant();
ZonedDateTime zdt = instant.atZone( zoneId ) ;