在 EST 与 UTC 中运行的服务器中的 LocalDate 和 LocalDateTime
LocalDate and LocalDateTime in a server which runs in EST vs UTC
我正在尝试了解 LocalDate 和 LocalDateTime。由于它们不携带时区信息,因此它如何在两个不同的时区为 now() 工作。
示例:
服务器 1(美国东部时间时区):
LocalDateTime.now() -> 2020-04-06T23:00:00.040
LocalDate.now()。 -> 2020-04-06
服务器 2(UTC 时区):
LocalDateTime.now() -> 值是多少?
LocalDate.now()。 -> 价值是多少? (注意 EST,执行时间是晚上 11 点)
此外,
如果我将以下日期字符串转换为 LocalDateTime,然后转换为 LocalDate,结果会是什么?
2020-04-06T23:00:00.000
偏移量随时间变化
2020 年 4 月 6 日,北美东海岸的大多数时区,例如 America/Montreal
和 America/New_York
使用 UTC 后四个小时的偏移量。
因此,在这些区域中,2020 年 4 月 6 日晚上 11 点同时是世界标准时间 7 日凌晨 3 点。 2020-04-06T23:00 加上四个小时得到 2020-04-07T03:00。添加四个小时使我们从 America/Port-au-Prince
和 America/Nassau
中使用的挂钟时间变为 UTC。
上述时区使用的偏移量仅比 UTC 晚半年 4 小时。这些地方的政客已决定在大约半年内遵守夏令时 (DST)。因此,半年他们将时钟提前一个小时以获得 -04:00 的偏移量 -04:00,而在今年晚些时候,他们会后退一个小时以获得 -05:00 的偏移量 -UTC。例如,今年早些时候 America/New_York
的晚上 11 点在 UTC 中将是 04:00 而不是四月份的 03:00 时间。
一月份的标准时间比 UTC 晚 5 小时。所以,晚上 11 点加上五个小时就是第二天凌晨 4 点。
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2020 , 1 , 6 , 23 , 0 , 0 , 0 , zNewYork ) ;
Instant instant = zdt.toInstant() ; // 2020-01-07T04:00Z
4 月的夏令时比 UTC 晚 四 小时。所以,晚上 11 点加上四个小时就是第二天凌晨 3 点。
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2020 , 4 , 6 , 23 , 0 , 0 , 0 , zNewYork ) ;
Instant instant = zdt.toInstant() ; // 2020-04-07T03:00Z
顺便说一句,DST 只是政客们改变其辖区时区使用的偏移量的众多原因之一。世界各地的政客都表现出对频繁更改偏移量的偏好。您的程序应始终期望时区会更改其偏移量。仅仅因为您的特定关注区域目前没有遵守 DST not 就意味着偏移量永远不会改变。
至于将 2020-04-06T23:00:00.000
解析为 LocalDateTime
,您将得到 2020-04-06T23:00:00.000
。忽略时区是 LocalDateTime
的重点。所以没有做任何调整。
您可能会认为 LocalDateTime
代表一个特定的地点。但是,不,它代表 any 地区或 all 地区。但从来没有任何一个特定的地方。对于特定地区,请使用 ZonedDateTime
。
伪时区
还有一点:EST
是不是时区。这种2-4个字母的字母代码不是实时时区,不是标准化的,甚至不是唯一的。例如,EST
是指 澳大利亚东部标准时间 还是 北美东部标准时间 ?是CST
中部标准时间还是中国标准时间?在您的日期时间处理中避免这些伪区域。
而且您碰巧使用了错误的伪代码。 2020 年 4 月 6 日,大部分东海岸时区都在观察夏令时 (DST)。所以他们会被认为是在“EDT”而不是“EST”。通过指定实时时区名称避免此问题。
实时时区使用Continent/Region
格式命名。有关实时时区列表,请参阅 Wikipedia。
从不调用 LocalDateTime.now
我无法想象调用 LocalDateTime.now
是正确的做法。确定当前时刻需要一个时区(或偏移量)。 LocalDateTime
根据定义没有时区或偏移量。当程序员编写 LocalDateTime.now
时,您可以打赌他们没有完全理解必要的概念。
当您调用 LocalDateTime.now
时,JVM 的当前默认时区将隐式用于捕获该时区区域中的人们所看到的当前时间。然后删除该时区的事实。
这个:
LocalDateTime.now()
...与此相同:
LocalDateDate.now( ZoneId.systemDefault() )
...这与获取特定时区中看到的当前时刻相同,然后删除时区信息:
ZonedDateTime.now( ZoneId.systemDefault() ).toLocalDateTime()
有关演示 LocalDateTime.now
的更多代码示例,请参阅
在哪里使用LocalDateTime
如果LocalDateTime
不适合获取当前时刻,也不适合跟踪任何时刻,那么这个class有什么合适的用途?三件事:代表任何地方,代表所有地方,以及预约未来的约会。
- 任何地方都类似于说明圣诞节何时开始。今年圣诞节从 2020-12-25T00:00 开始,无论您身在何处。当然,这意味着圣诞节首先在基里巴斯午夜后开始,在日本在午夜后开始,在突尼斯甚至在午夜后开始,在芝加哥在午夜后更晚。
- 所有地方都像是在声明我们公司的政策,即我们在德里、杜塞尔多夫和底特律的所有工厂的午休时间都安排在 12:30。因此,2020 年 4 月 6 日,休息时间为 2020-04-06T12:30:00。这种休息将首先发生在德里,几个小时后在杜塞尔多夫,甚至更多小时后在底特律。
- 无论时区偏移量是否发生变化,如果您打算保持同一时间的未来约会必须在没有偏移量的情况下进行记录。如果您的下一次牙科预约是在六个月后的下午 3 点,我们希望记录下午 3 点而不考虑偏移量。如果政客们要改变偏移量,我们仍然希望在该地区该日期的时钟敲响三点时开始任命。
设置约会。
LocalDateTime appointment = LocalDateTime.of( 2021 , 1 , 23 , 15 , 0 , 0 , 0 ) ;
确定制作日历的时刻。每次你这样做,如果政治家改变了这个时区的规则,你可能会得到不同的结果。
ZoneId z = ZoneId.of ( "America/Panama" ) ;
ZonedDateTime dueToArrive = appointment.atZone( z ) ;
LocalDate
至于LocalDate
,我们在上面的例子中看到日期取决于时区。对于任何给定时刻,全球各地的日期因时区而异。在日本东京可能是“明天”,而在加拿大魁北克蒙特利尔仍然是“昨天”。
因此,您必须在询问当前日期时指定时区。
LocalDate ld = LocalDate.now( ZoneId.of( "Asia/Kolkata" ) ) ;
如果省略时区,则隐式应用 JVM 当前的默认时区。所以 LocalDate.now()
变成 LocalDate.now( ZoneId.systemDefault() )
。我建议明确指定 desired/expected 区域,而不是依赖隐式默认值。
服务器时区
你说:
server which runs in EST vs UTC
仅供参考,服务器通常应设置为 UTC。您的大部分思考、编程、日志记录等都应该在 UTC 中完成。学会将 UTC 视为唯一真实时间,所有其他时区都只是变化而已。
作为一名程序员,您永远不应依赖默认时区。那是你无法控制的。用户或系统管理员可以很容易地更改该默认值。此外,JVM 内任何应用程序的任何线程中的任何代码都可以通过调用 TimeZone.setDefault
立即更改 JVM 的当前默认时间。因此,即使 在 应用程序执行期间,默认值也可以随时更改。
为防止混淆,将明确的时区传递给 now()
并亲自查看:
ZoneId easternTime = ZoneId.of("America/Montreal");
System.out.println(LocalDateTime.now(easternTime));
System.out.println(LocalDateTime.now(ZoneOffset.UTC));
System.out.println(LocalDate.now(easternTime));
System.out.println(LocalDate.now(ZoneOffset.UTC));
我刚才运行时输出:
2020-04-06T09:56:17.381558
2020-04-06T13:56:17.385215
2020-04-06
2020-04-06
虽然 LocalDateTime
和 LocalDate
不包含任何时区信息是正确的,但它们的 now
方法确实使用了时区。传递给他们的那个,或者如果您使用无参数变体,JVM 的默认时区。
您还问过:
Also, If I convert below date string to LocalDateTime and then
toLocalDate, what would be the outcome?
2020-04-06T23:00:00.000
为什么不也试试呢?
LocalDateTime ldt = LocalDateTime.parse("2020-04-06T23:00:00.000");
System.out.println(ldt);
LocalDate ld = ldt.toLocalDate();
System.out.println(ld);
2020-04-06T23:00
2020-04-06
从 LocalDateTime
转换为 LocalDate
不涉及任何时区(或 UTC 偏移量)。时间部分直接丢弃,日期部分保持不变
我正在尝试了解 LocalDate 和 LocalDateTime。由于它们不携带时区信息,因此它如何在两个不同的时区为 now() 工作。
示例:
服务器 1(美国东部时间时区):
LocalDateTime.now() -> 2020-04-06T23:00:00.040 LocalDate.now()。 -> 2020-04-06
服务器 2(UTC 时区):
LocalDateTime.now() -> 值是多少? LocalDate.now()。 -> 价值是多少? (注意 EST,执行时间是晚上 11 点)
此外, 如果我将以下日期字符串转换为 LocalDateTime,然后转换为 LocalDate,结果会是什么?
2020-04-06T23:00:00.000
偏移量随时间变化
2020 年 4 月 6 日,北美东海岸的大多数时区,例如 America/Montreal
和 America/New_York
使用 UTC 后四个小时的偏移量。
因此,在这些区域中,2020 年 4 月 6 日晚上 11 点同时是世界标准时间 7 日凌晨 3 点。 2020-04-06T23:00 加上四个小时得到 2020-04-07T03:00。添加四个小时使我们从 America/Port-au-Prince
和 America/Nassau
中使用的挂钟时间变为 UTC。
上述时区使用的偏移量仅比 UTC 晚半年 4 小时。这些地方的政客已决定在大约半年内遵守夏令时 (DST)。因此,半年他们将时钟提前一个小时以获得 -04:00 的偏移量 -04:00,而在今年晚些时候,他们会后退一个小时以获得 -05:00 的偏移量 -UTC。例如,今年早些时候 America/New_York
的晚上 11 点在 UTC 中将是 04:00 而不是四月份的 03:00 时间。
一月份的标准时间比 UTC 晚 5 小时。所以,晚上 11 点加上五个小时就是第二天凌晨 4 点。
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2020 , 1 , 6 , 23 , 0 , 0 , 0 , zNewYork ) ;
Instant instant = zdt.toInstant() ; // 2020-01-07T04:00Z
4 月的夏令时比 UTC 晚 四 小时。所以,晚上 11 点加上四个小时就是第二天凌晨 3 点。
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2020 , 4 , 6 , 23 , 0 , 0 , 0 , zNewYork ) ;
Instant instant = zdt.toInstant() ; // 2020-04-07T03:00Z
顺便说一句,DST 只是政客们改变其辖区时区使用的偏移量的众多原因之一。世界各地的政客都表现出对频繁更改偏移量的偏好。您的程序应始终期望时区会更改其偏移量。仅仅因为您的特定关注区域目前没有遵守 DST not 就意味着偏移量永远不会改变。
至于将 2020-04-06T23:00:00.000
解析为 LocalDateTime
,您将得到 2020-04-06T23:00:00.000
。忽略时区是 LocalDateTime
的重点。所以没有做任何调整。
您可能会认为 LocalDateTime
代表一个特定的地点。但是,不,它代表 any 地区或 all 地区。但从来没有任何一个特定的地方。对于特定地区,请使用 ZonedDateTime
。
伪时区
还有一点:EST
是不是时区。这种2-4个字母的字母代码不是实时时区,不是标准化的,甚至不是唯一的。例如,EST
是指 澳大利亚东部标准时间 还是 北美东部标准时间 ?是CST
中部标准时间还是中国标准时间?在您的日期时间处理中避免这些伪区域。
而且您碰巧使用了错误的伪代码。 2020 年 4 月 6 日,大部分东海岸时区都在观察夏令时 (DST)。所以他们会被认为是在“EDT”而不是“EST”。通过指定实时时区名称避免此问题。
实时时区使用Continent/Region
格式命名。有关实时时区列表,请参阅 Wikipedia。
从不调用 LocalDateTime.now
我无法想象调用 LocalDateTime.now
是正确的做法。确定当前时刻需要一个时区(或偏移量)。 LocalDateTime
根据定义没有时区或偏移量。当程序员编写 LocalDateTime.now
时,您可以打赌他们没有完全理解必要的概念。
当您调用 LocalDateTime.now
时,JVM 的当前默认时区将隐式用于捕获该时区区域中的人们所看到的当前时间。然后删除该时区的事实。
这个:
LocalDateTime.now()
...与此相同:
LocalDateDate.now( ZoneId.systemDefault() )
...这与获取特定时区中看到的当前时刻相同,然后删除时区信息:
ZonedDateTime.now( ZoneId.systemDefault() ).toLocalDateTime()
有关演示 LocalDateTime.now
的更多代码示例,请参阅
在哪里使用LocalDateTime
如果LocalDateTime
不适合获取当前时刻,也不适合跟踪任何时刻,那么这个class有什么合适的用途?三件事:代表任何地方,代表所有地方,以及预约未来的约会。
- 任何地方都类似于说明圣诞节何时开始。今年圣诞节从 2020-12-25T00:00 开始,无论您身在何处。当然,这意味着圣诞节首先在基里巴斯午夜后开始,在日本在午夜后开始,在突尼斯甚至在午夜后开始,在芝加哥在午夜后更晚。
- 所有地方都像是在声明我们公司的政策,即我们在德里、杜塞尔多夫和底特律的所有工厂的午休时间都安排在 12:30。因此,2020 年 4 月 6 日,休息时间为 2020-04-06T12:30:00。这种休息将首先发生在德里,几个小时后在杜塞尔多夫,甚至更多小时后在底特律。
- 无论时区偏移量是否发生变化,如果您打算保持同一时间的未来约会必须在没有偏移量的情况下进行记录。如果您的下一次牙科预约是在六个月后的下午 3 点,我们希望记录下午 3 点而不考虑偏移量。如果政客们要改变偏移量,我们仍然希望在该地区该日期的时钟敲响三点时开始任命。
设置约会。
LocalDateTime appointment = LocalDateTime.of( 2021 , 1 , 23 , 15 , 0 , 0 , 0 ) ;
确定制作日历的时刻。每次你这样做,如果政治家改变了这个时区的规则,你可能会得到不同的结果。
ZoneId z = ZoneId.of ( "America/Panama" ) ;
ZonedDateTime dueToArrive = appointment.atZone( z ) ;
LocalDate
至于LocalDate
,我们在上面的例子中看到日期取决于时区。对于任何给定时刻,全球各地的日期因时区而异。在日本东京可能是“明天”,而在加拿大魁北克蒙特利尔仍然是“昨天”。
因此,您必须在询问当前日期时指定时区。
LocalDate ld = LocalDate.now( ZoneId.of( "Asia/Kolkata" ) ) ;
如果省略时区,则隐式应用 JVM 当前的默认时区。所以 LocalDate.now()
变成 LocalDate.now( ZoneId.systemDefault() )
。我建议明确指定 desired/expected 区域,而不是依赖隐式默认值。
服务器时区
你说:
server which runs in EST vs UTC
仅供参考,服务器通常应设置为 UTC。您的大部分思考、编程、日志记录等都应该在 UTC 中完成。学会将 UTC 视为唯一真实时间,所有其他时区都只是变化而已。
作为一名程序员,您永远不应依赖默认时区。那是你无法控制的。用户或系统管理员可以很容易地更改该默认值。此外,JVM 内任何应用程序的任何线程中的任何代码都可以通过调用 TimeZone.setDefault
立即更改 JVM 的当前默认时间。因此,即使 在 应用程序执行期间,默认值也可以随时更改。
为防止混淆,将明确的时区传递给 now()
并亲自查看:
ZoneId easternTime = ZoneId.of("America/Montreal");
System.out.println(LocalDateTime.now(easternTime));
System.out.println(LocalDateTime.now(ZoneOffset.UTC));
System.out.println(LocalDate.now(easternTime));
System.out.println(LocalDate.now(ZoneOffset.UTC));
我刚才运行时输出:
2020-04-06T09:56:17.381558 2020-04-06T13:56:17.385215 2020-04-06 2020-04-06
虽然 LocalDateTime
和 LocalDate
不包含任何时区信息是正确的,但它们的 now
方法确实使用了时区。传递给他们的那个,或者如果您使用无参数变体,JVM 的默认时区。
您还问过:
Also, If I convert below date string to LocalDateTime and then toLocalDate, what would be the outcome?
2020-04-06T23:00:00.000
为什么不也试试呢?
LocalDateTime ldt = LocalDateTime.parse("2020-04-06T23:00:00.000");
System.out.println(ldt);
LocalDate ld = ldt.toLocalDate();
System.out.println(ld);
2020-04-06T23:00 2020-04-06
从 LocalDateTime
转换为 LocalDate
不涉及任何时区(或 UTC 偏移量)。时间部分直接丢弃,日期部分保持不变