Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/magento/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
与Java时间解析UTC的混淆_Java_Parsing_Datetime_Java Time_Localtime - Fatal编程技术网

与Java时间解析UTC的混淆

与Java时间解析UTC的混淆,java,parsing,datetime,java-time,localtime,Java,Parsing,Datetime,Java Time,Localtime,我对java时间中的时间处理感到困惑。长期以来,我一直假设,如果将时间戳指定为zulu时间,java将处理与本地时间相关的偏移量 举例说明。我目前在英国夏令时,其偏移量为UTC+1。考虑到这一点,我希望这次祖鲁人: 2016-09-12T13:15:17.309Z 将来 2016-09-12T14:15:17.309 解析后的LocalDateTime。这是因为我的默认systemtime设置为BST,并且上面的时间戳(zulu时间)指定它是UTC时间 然而,请考虑这个样本:

我对java时间中的时间处理感到困惑。长期以来,我一直假设,如果将时间戳指定为zulu时间,java将处理与本地时间相关的偏移量

举例说明。我目前在英国夏令时,其偏移量为UTC+1。考虑到这一点,我希望这次祖鲁人:

2016-09-12T13:15:17.309Z
将来

2016-09-12T14:15:17.309 
解析后的LocalDateTime。这是因为我的默认systemtime设置为BST,并且上面的时间戳(zulu时间)指定它是UTC时间

然而,请考虑这个样本:

        String ts = "2016-09-12T13:15:17.309Z";
        LocalDateTime parse = LocalDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME);
        System.out.println(parse);
这将打印:

2016-09-12T13:15:17.309
因此,解析为LocalDateTime的时间戳不会被识别为UTC时间,而是直接被视为localtime。 所以我想,也许我需要将其解析为ZonedDateTime,并将其转换为LocalDateTime,以便获得正确的本地时间。通过此测试:

        String ts = "2016-09-12T13:15:17.309Z";
        ZonedDateTime parse = ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME);
        System.out.println(parse);
        System.out.println(parse.toLocalDateTime());
我得到的结果是:

2016-09-12T13:15:17.309Z
2016-09-12T13:15:17.309
两个日期的输出相同

我能找到的唯一正确解析方法是:

    String ts = "2016-09-12T13:15:17.309Z";
    Instant instant = Instant.parse(ts); // parses UTC
    LocalDateTime ofInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    System.out.println(instant);
    System.out.println(ofInstant);
这张照片是:

2016-09-12T13:15:17.309Z
2016-09-12T14:15:17.309
这是正确的

因此,问题是:

  • java time不应该识别UTC时间戳并将其解析为正确的系统默认值吗
  • 如何使用
    LocalDateTime#parse
    方法获得正确的结果
  • 我是否应该现在对所有内容使用
    Instant
    ,并放弃解析

问题在于
jersey/jackson
的java时间模块使用ISO格式和常规的
LocalDateTime#parse
方法解析时间戳。我意识到我的时间并没有中断,因为它们被视为
LocalTime
,而事实上它们在祖鲁时间

你误解了我们的目的

要引用课堂文档,请执行以下操作:

ISO-8601日历系统中没有时区的日期时间,如{@code 2007-12-03T10:15:30}

此类不存储或表示时区。相反,它是对日期的描述,用于生日,与挂钟上显示的当地时间相结合。如果没有诸如偏移量或时区之类的附加信息,它不能表示时间线上的某个瞬间

所以它的明确目的只是表示一个没有时区的日期和时间。它的目的不是表示本地时区中的日期和时间

因此,每次转换只会剥离时区

因此,出于您的目的,您需要一个
zoneDateTime
ZoneId.systemDefault()
,正如您在第三个示例中已经使用的那样

对于第二个示例,这可能是:

String ts = "2016-09-12T13:15:17.309Z";
ZonedDateTime parse = 
    ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME)
        .withZoneSameInstant(ZoneId.systemDefault());
System.out.println(parse);
System.out.println(parse.toLocalDateTime());
tl;博士
  • 不要使用
  • 使用&
例如:

Instant.parse( "2016-09-12T13:15:17.309Z" )
       .atZone( ZoneId.of( "Europe/London" ) )
       .toString();
2016-09-12T14:15:17.309+01:00[欧洲/伦敦]

细节 答案是正确的。您误解了
LocalDateTime
类的含义。它不代表特定地区的日期和时间。恰恰相反,它根本不代表一个实际的时刻

我建议将
Instant
作为java.time中的基本构建块类。该类表示时间线上的一个时刻,分辨率为(小数点的九(9)位)

您的输入字符串符合ISO 8601格式,默认情况下,
Instant
类使用该格式来解析和生成字符串表示。末尾的
Z
Zulu
的缩写,表示UTC。无需指定格式化模式

Instant instant = Instant.parse( "2016-09-12T13:15:17.309Z" );
作为一名程序员,您应该主要学习在UTC中思考和工作。忘掉你自己的时区吧。将UTC视为唯一的真实时间。仅在需要时将时区作为变量应用

大陆/地区
的格式指定,例如,或
太平洋/奥克兰
。切勿使用3-4个字母的缩写,例如
BST
EST
IST
,因为它们不是真正的时区,不标准化,甚至不是唯一的(!)。如果您所说的英国夏令时是指英国夏季时间,那么实际的时区名称是。time类将确定如何调整任何异常,包括夏令时(DST)


关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

该项目现已启动,建议迁移到java.time

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

从哪里获得java.time类

  • 后来
    • 内置的
    • 标准JavaAPI的一部分,带有捆绑实现
    • Java9添加了一些次要功能和修复
    • 大部分java.time功能都在中向后移植到Java6和Java7
    • 该项目专门针对Android采用了Three Ten Backport(如上所述)

该项目使用其他类扩展了java.time。这个项目是java.time将来可能添加的一个试验场。您可能会在这里找到一些有用的类,例如、、和。

您的示例看起来像是在进行示例3中的即时对话。你是对的,我误解了LocalDateTime的含义。啊。。时区:)谢谢,所以ZoneDateTime将时区识别为“Z”,并自动将其解释为UTC(正是我想要的)-是吗?@pandaadb是的,这可能只是另一种书写方式。@pandaadb是的,解析器正确识别它。只是到
LocalDateTime
的转换确实会去除它。
ZoneId z = ZoneId.of( "Europe/London" );
ZonedDateTime zdt = instant.atZone( z );