SimpleDateFormat parse 失去时区tl;博士详关于 java.time

2022-08-31 16:12:07

法典:

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
    sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
    System.out.println(new Date());
    try {
        String d = sdf.format(new Date());
        System.out.println(d);
        System.out.println(sdf.parse(d));
    } catch (Exception e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    }

输出:

Thu Aug 08 17:26:32 GMT+08:00 2013
2013.08.08 09:26:32 GMT
Thu Aug 08 17:26:32 GMT+08:00 2013

请注意,格式正确设置为 GMT,但丢失了 GMT 详细信息。我知道我可以使用并解决这个问题,但是这种现象背后的原因是什么?format()Dateparse()substring()

这是一个重复的问题,没有任何答案。

编辑:让我以另一种方式提出问题,检索Date对象的方法是什么,以便它始终处于GMT状态?


答案 1

我需要的只是这个:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));

SimpleDateFormat sdfLocal = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");

try {
    String d = sdf.format(new Date());
    System.out.println(d);
    System.out.println(sdfLocal.parse(d));
} catch (Exception e) {
    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
}

输出:有点可疑,但我只想让日期保持一致

2013.08.08 11:01:08
Thu Aug 08 11:01:08 GMT+08:00 2013

答案 2

tl;博士

检索Date对象的方法是什么,以便它始终处于GMT状态?

Instant.now() 

您正在使用麻烦的令人困惑的旧日期时间类,这些类现在已被java.time类所取代。

Instant= 世界协调时

Instant 类以 UTC 格式表示时间轴上的某个时刻,分辨率为纳秒(最多九 (9) 位小数)。

Instant instant = Instant.now() ; // Current moment in UTC.

国际标准化组织 ISO 8601

要将此数据作为文本进行交换,请专门使用标准 ISO 8601 格式。这些格式被合理地设计为明确无误,易于机器处理,并且易于人们在许多文化中阅读。

java.time 类在解析和生成字符串时默认使用标准格式。

String output = instant.toString() ;  

2017-01-23T12:34:56.123456789Z

时区

如果要查看与特定区域的挂钟时间中显示的时刻相同的时刻,请应用 a 以获取 .ZoneIdZonedDateTime

以 的格式指定适当的时区名称,例如 美国/蒙特利尔非洲/卡萨布兰卡或 。切勿使用3-4个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。continent/regionPacific/AucklandESTIST

ZoneId z = ZoneId.of( "Asia/Singapore" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same simultaneous moment, same point on the timeline.

IdeOne.com 现场查看此代码。

请注意八小时的差异,因为亚洲/新加坡的时区当前与 UTC 的偏移量为 +08:00。相同的时刻,不同的挂钟时间。

瞬视(): 2017-01-23T12:34:56.123456789Z

zdt.toString(): 2017-01-23T20:34:56.123456789+08:00[亚洲/新加坡]

转换

避免使用旧类。但如果必须,您可以转换。查看添加到旧类的新方法。java.util.Date

java.util.Date date = Date.from( instant ) ;

...走另一条路...

Instant instant = myJavaUtilDate.toInstant() ;

仅日期

对于仅日期,请使用 。LocalDate

LocalDate ld = zdt.toLocalDate() ;

关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,如java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

从哪里获取 java.time 类?

ThreeTen-Extra 项目通过其他类扩展了 java.time。这个项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuarter