JAVA 时区问题 EDT 与 EST
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3933368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JAVA TimeZone issue EDT Vs EST
提问by ViV
I a newbie to java and hence haven't been able figure this out since quite some time.
我是java的新手,因此很长一段时间以来一直无法解决这个问题。
I am using Windows XP and the machine is set to TimeZone: Eastern Time (US & Canada).
我使用的是 Windows XP 并且机器设置为 TimeZone: Eastern Time (US & Canada)。
I have a Java application, which takes the current system time and timezone info and writes a string like: 20101012 15:56:00 EST, to a file.
我有一个 Java 应用程序,它获取当前系统时间和时区信息,并将一个字符串写入一个文件,如:20101012 15:56:00 EST。
The last piece of Date above, i.e.: the timezone, changes from EST to EDT as i change my system date.
上面的最后一段日期,即:时区,在我更改系统日期时从 EST 更改为 EDT。
Being precise: From November(eg: Nov2009) to March (Mar 2010), it is EST, otherwise EDT.
准确地说:从十一月(例如:Nov2009)到三月(2010 年 3 月),它是 EST,否则是 EDT。
EST is what I want ALWAYSand not EDT.
EST是什么,我想总是不EDT。
Is there any particular class / function, by which I can always read it as EST?
是否有任何特定的类/函数,我可以通过它始终将其作为 EST 读取?
Awaiting for response.
等待回应。
Thanks for your replies. Well, I forgot to mention a few things.
感谢您的回复。好吧,我忘了提几件事。
I want my machine to be set to: Eastern Time (US & Canada) in the windows time zone settings.
In simple terms, What i want to do is: get my machine time, and write it to a text file
I am aware of the daylight saving which happens from March to Nov.
我希望我的机器在 Windows 时区设置中设置为:东部时间(美国和加拿大)。
简单来说,我想做的是:获取我的机器时间,并将其写入文本文件
我知道从三月到十一月发生的夏令时。
But the problem is, when I write my machine time to the file, it is written as 2010 01 12 15:56:00 EST if daylight saving (DST) is not present and as 20101012 15:56:00 EDT, if DST is present. My concern is, whether it is DST or not, I want to write EST always.
但问题是,当我将我的机器时间写入文件时,如果不存在夏令时 (DST),则将其写为 2010 01 12 15:56:00 EDT,如果 DST 为 20101012 15:56:00 EDT展示。我关心的是,不管是不是 DST,我都想一直写 EST。
采纳答案by Mike Axiak
I don't think you should do what you are suggesting.
我认为你不应该按照你的建议去做。
You are saying that regardless of what your system timezone is currently (Eastern Time is NOT your time zone, but UTC+5 or +4 is), you want it to display EST. This is just plainly wrong. Suppose it's in the summer, and your computer thinks it's 2010/6/15 15:00 locally. You print the current time and you get:
您是说无论您的系统时区当前是什么(东部时间不是您的时区,而是 UTC+5 或 +4),您都希望它显示 EST。这显然是错误的。假设现在是夏天,您的计算机认为本地是 2010/6/15 15:00。您打印当前时间并获得:
The time I print this out at: 2010 06 15 15:00:00 EDT
我打印出来的时间:2010 06 15 15:00:00 EDT
For whatever reason, you think that the EDT is unpleasing, and so you change it to EST:
无论出于何种原因,您认为 EDT 令人不快,因此将其更改为 EST:
I print this out at: 2010 06 15 15:00:00 EST
我在以下时间打印出来:2010 06 15 15:00:00 EST
however, if you then send that snippet to someone else within the next hour, they'll be forced to think you traveled from the future! Since 15:00:00 EST is 16:00:00 EDT.
但是,如果您在下一小时内将该片段发送给其他人,他们将被迫认为您来自未来!由于 15:00:00 EST 是 16:00:00 EDT。
回答by Michael Borgwardt
the machine is set to TimeZone: Eastern Time (US & Canada).
机器设置为时区:东部时间(美国和加拿大)。
That's not a real time zone (neither are EDT and EST). A time zone (as understood by Java) is something like "America/Phoenix", which is an ID for an administrative timezone that has both a base offset and (optionally) switches to daylight savings time at specific dates. Both of these can change, and it's necessary to take such changes into account when interpreting historical dates.
这不是一个真正的时区(EDT 和 EST 都不是)。时区(如 Java 所理解的)类似于“America/Phoenix”,它是管理时区的 ID,它具有基本偏移量和(可选)在特定日期切换到夏令时。这两者都可能发生变化,在解释历史日期时有必要考虑这些变化。
Thus, if you don't want to have DST switches, choose a timezone that does not observe DST. It is possible that there is no such timezone and trying to act like there is would introduce impossible dates.
因此,如果您不想使用 DST 开关,请选择不遵守 DST 的时区。可能没有这样的时区,并且试图表现得像那样会引入不可能的日期。
回答by Ophidian
It should be noted that during the Summer months of the Eastern timezone, pretty much every major center uses Daylight Savings Time, so you are correctly being shown the time that people in that timezone care about.
应该注意的是,在东部时区的夏季月份,几乎每个主要中心都使用夏令时,因此您可以正确地看到该时区人们关心的时间。
If you want it to be a specific timezone, rather than the default/system timezone, then you can force the TimeZoneto EST via something like this:
如果您希望它是特定时区,而不是默认/系统时区,那么您可以通过以下方式强制时区为 EST:
TimeZone est = TimeZone.getTimeZone("EST");
Although as Michael mentioned above, the documentation recommends using a local full name such as "America/New York" rather than the general timezone abbreviation.
尽管正如 Michael 上面提到的,文档建议使用本地全名,例如“America/New York”,而不是一般的时区缩写。
If you want to claim that it really is EST even though you know it to be EDT, then I suppose you could do the following: use a SimpleDateFormat
instance with a custom pattern that doesn't include the timezone information, then tack "EST" onto the end of the String you write out.
如果您想声称它确实是 EST,即使您知道它是 EDT,那么我想您可以执行以下操作:使用具有SimpleDateFormat
不包含时区信息的自定义模式的实例,然后将“EST”添加到你写出的字符串的结尾。
回答by Devon_C_Miller
I would create a custom zone:
我会创建一个自定义区域:
TimeZone alwaysEst = TimeZone.getTimeZone("EST+5");
That will report as EST and will always be 5 hours ahead of UTC. In particular, do not choose an existing timezone or you will eventually get burned when a zone update changes the definition.
这将报告为 EST,并且始终比 UTC 早 5 小时。特别是,不要选择现有的时区,否则当区域更新更改定义时,您最终会被烧毁。
Do be aware that by forcing EST the dates you log will only match the time displayed by the system for 5 months out of the year. The other 7 months you'll be an hour off. It may simplify parsing the file, but it will confuse users.
请注意,通过强制 EST,您记录的日期只会与系统显示的一年中 5 个月的时间相匹配。其他 7 个月您将休息一个小时。它可能会简化解析文件,但会混淆用户。
回答by L. Holanda
Your question is still not clear.
你的问题还是不清楚。
I didn't undestand if you simply want to force 'EST' chars, even if your machine is set to automatically chage DST, or what you want is to get the actual time on EST.
我不明白您是否只是想强制使用“EST”字符,即使您的机器设置为自动更改 DST,或者您想要的是获取 EST 的实际时间。
So you have two options:
所以你有两个选择:
Your machine time is set to 2:15pm and DST in on effect, and you want to write 2:15pm EST (which is not the correct actual time) you should use SimpleDateFormat. This way, you will be lying about the time. But, anyway, you know what best fits for you.
Your machine time is set to 2:15pm and DST in on effect, and you want to write 1:15pm EST, you should use: TimeZone.setDefault(TimeZone.getTimeZone("EST"))
您的机器时间设置为下午 2:15 并且 DST 生效,并且您想写入 2:15pm EST(这不是正确的实际时间),您应该使用 SimpleDateFormat。这样,你就会在时间上撒谎。但是,无论如何,您知道什么最适合您。
您的机器时间设置为下午 2:15 并且 DST 生效,并且您想写 1:15pm EST,您应该使用: TimeZone.setDefault(TimeZone.getTimeZone("EST"))
回答by Stephen P
The solution depends on why you're writing this time out and what you want to do with it when you read it back in (what it's going to be used to do, not "what you want"). Always writing it out as EST is a misrepresentation of fact. When EDT is in effect it is not, in fact, EST. If you're trying to track some "absolute" point in time I recommend working in GMTinstead of any timezone.
解决方案取决于您这次为什么要写出来,以及当您读回它时您想用它做什么(它将用来做什么,而不是“您想要什么”)。总是把它写成 EST 是对事实的歪曲。当 EDT 生效时,它实际上不是EST。如果您尝试跟踪某个“绝对”时间点,我建议您使用GMT而不是任何时区。
回答by Basil Bourque
Date-time work is tricky
日期时间工作很棘手
I a newbie to java and hence haven't been able figure this out since quite some time.
我是java的新手,因此很长一段时间以来一直无法解决这个问题。
Date-time handling is surprisingly tricky for even experienced programmers. The concepts are rather slippery. All kinds of practices have developed by various people in various industries, thereby complicating matters.
即使对于有经验的程序员来说,日期时间处理也非常棘手。这些概念相当模糊。各行各业的各行各业的人都制定了各种做法,使事情复杂化。
Fortunately, Java now has built-in the industry-leading framework for date-time work: java.timedefined in JSR 310.
幸运的是,Java 现在内置了业界领先的日期时间工作框架:JSR 310 中定义的java.time。
Explicitly specify desired/expected time zone
明确指定所需/预期的时区
I am using Windows XP and the machine is set to TimeZone:
我使用的是 Windows XP 并且机器设置为 TimeZone:
The host OS should not affect your date-time handling work in Java.
主机操作系统不应影响您在 Java 中的日期时间处理工作。
Never rely on the host machine's current default time zone. That default can change at any time, so it is outside your control as a programmer. Instead, specify your desired/expected time zone within your Java code.
永远不要依赖主机的当前默认时区。该默认值可以随时更改,因此作为程序员,它不受您的控制。相反,请在 Java 代码中指定所需/预期的时区。
ZoneId z = ZoneId.of( "America/New_York" ) ;
EDT
/ Eastern Time
is nota time zone
EDT
/Eastern Time
是不是一个时区
… Eastern Time (US & Canada).
... 东部时间(美国和加拿大)。
There is not really such a thing as "Eastern Time". This imprecise term is a grab-bag collective noun used to describe the current offset-from-UTC used by various time zones. When doing programming, forget all about "Eastern Time", "EST", and other pseudo-zones.
没有真正的“东部时间”这样的东西。这个不精确的术语是一个抓包集合名词,用于描述不同时区使用的当前与 UTC 的偏移量。在进行编程时,忘记所有关于“东部时间”、“东部时间”和其他伪区域的内容。
Offset versus zone
偏移与区域
Understand that an offset is merely a number of hours-minutes-seconds ahead or behind the prime meridian. An offset looks like +05:30
or -05:00
.
了解偏移量只是本初子午线之前或之后的几个小时-分-秒数。偏移量看起来像+05:30
或-05:00
。
A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region. The rules of a time zone are set capriciously by politicians, and change with surprising frequency.
时区要多得多。时区是特定地区人民使用的偏移量的过去、现在和未来变化的历史记录。时区的规则由政客反复无常地设定,并且以惊人的频率变化。
A proper time zone name is composed as Continent/Region
such as America/Montreal
or America/New_York
. See this list of zones at Wikipedia(may not be up-to-date).
一份适当的时区名称的组成Continent/Region
,如America/Montreal
或America/New_York
。请参阅维基百科上的区域列表(可能不是最新的)。
ISO 8601
ISO 8601
writes a string like: 20101012 15:56:00 EST, to a file.
将字符串如:20101012 15:56:00 EST 写入文件。
We have a formal international standard for the formats of date-time values being serialized as text: ISO 8601. Do not invent your own! The standard formats are wisely designed to be practical, easy to parse by machine, and easy to read by humans across cultures.
对于序列化为文本的日期时间值格式,我们有一个正式的国际标准:ISO 8601。不要自己发明!标准格式被明智地设计为实用、易于机器解析并且易于跨文化的人类阅读。
For example, nearly 4 PM on the twelveth of October in 2010 in Québec would be:
例如,魁北克 2010 年 10 月 12 日下午近 4 点将是:
2010-10-12T15:56-04:00
2010-10-12T15:56-04:00
The java.timeclasses use the ISO 8601 formats by default when parsing/generatingtext. So no need to specify a formatting pattern. Use ZonedDateTime
to represent a moment as seen through a particular time zone.
该java.time类时默认使用ISO 8601种格式的解析/生成文本。所以不需要指定格式模式。使用ZonedDateTime
表示了一下经过特定时间段观察。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2010 , 10 , 12 , 15 , 56 , 0 , 0 , z ) ;
The ZonedDateTime::toString
method wisely extends the standard format to append the name of the zone in square brackets.
该ZonedDateTime::toString
方法明智地扩展了标准格式,将区域名称附加在方括号中。
zdt.toString(): 2010-10-12T15:56-04:00[America/Montreal]
zdt.toString(): 2010-10-12T15:56-04:00[美国/蒙特利尔]
Parsing such a string.
解析这样的字符串。
ZonedDateTime zdt2 = ZonedDateTime.parse( "2010-10-12T15:56-04:00[America/Montreal]" ) ;
boolean sameZdts = zdt.equals ( zdt2 ) ;
sameZdts: true
sameZdts: 真
See that code run live at IdeOne.com.
Daylight Saving Time (DST)
夏令时 (DST)
EST is what I want ALWAYS and not EDT.
EST 是我一直想要的,而不是 EDT。
Your goal does not make sense.
你的目标没有意义。
Those pseudo-zones (EST
& EDT
) are meant to indicate when Daylight Saving Time (DST)is in effect and when standard time is in effect. So wanting to always be using standard time in a region (a time zone) that observes DST is a contradiction, and not possible.
这些伪区域 ( EST
& EDT
) 旨在指示夏令时 (DST)何时生效以及标准时间何时生效。因此,想要始终在遵守 DST 的地区(时区)中使用标准时间是矛盾的,而且是不可能的。
So if you are trying to represent a moment as seen through the wall-clock time used by the people of a particular region (a time zone), you should specify the date, the time-of-day, and the time zone via ZoneId
, and let java.timehandle the issue of whether DST is in effect or not.
因此,如果您试图通过特定地区(时区)的人们使用的挂钟时间来表示某个时刻,则应通过以下方式指定日期、时间和时区ZoneId
,并让java.time处理 DST 是否生效的问题。
LocalDate ld = LocalDate.of( 2010 , Month.OCTOBER , 12 ) ;
LocalTime lt = LocalTime.of( 15 , 56 , 0 ) ;
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
zdt.toString(): 2010-10-12T15:56-04:00[America/New_York]
zdt.toString(): 2010-10-12T15:56-04:00[美国/纽约]
To see that same moment in UTC, extract an Instant
. Same moment, same point on the timeline, different wall-clock-time.
要在 UTC 中查看同一时刻,请提取Instant
. 同一时刻,时间线上的同一点,不同的挂钟时间。
Instant instant = zdt.toInstant() ;
instant.toString(): 2010-10-12T19:56:00Z
Instant.toString(): 2010-10-12T19:56:00Z
See that code above run live at IdeOne.com.
请参阅上面的代码在 IdeOne.com 上实时运行。
Booking future appointment
预约未来约会
am dealing with a server to whom I need to tell: "Do a task at 20101015 15:30:30 xxx" xxx being the timezone. The server understands only EST and not EDT whatever month it is. Hence, EDT is unpleasing.
我正在处理我需要告诉的服务器:“在 20101015 15:30:30 xxx 执行任务” xxx 是时区。无论是哪个月,服务器都只能识别 EST 而不能识别 EDT。因此,EDT 令人不快。
Regarding the EST versus EDT, we already covered your concern as senseless/irrelevant. These flags for standard time versus Daylight Saving Time automatically switch over when a particular time zone cuts over to/from DST.
关于 EST 与 EDT,我们已经将您的担忧视为毫无意义/无关紧要。当特定时区切换到/从 DST 切换时,这些标准时间与夏令时的标志会自动切换。
As for booking an appointment in the future, you cannot know if Daylight Saving Time (DST) is in effect or not. You cannot know if some otherwacky adjustment has been made to the rules of your time zone.
至于日后预约,您无法知道夏令时(DST)是否生效。您无法知道是否对您所在的时区规则进行了其他一些古怪的调整。
As mentioned above, time zone definitions are controlled by capricious politicians. Around the world, they have shown a surprising penchant for frequent changes. The US has changed the dates of their DST cutovers multiple times over the decades. Russia has adopted and dropped DST multiple times in recent years. The latest fad is to stay on DST year-round, done recently by Turkey and Morocco, and the United States is on the verge of going this way as well.
如上所述,时区定义由反复无常的家控制。在世界各地,他们都表现出对频繁变化的惊人偏好。几十年来,美国多次更改了夏令时转换的日期。近年来,俄罗斯多次采用和取消夏令时。最新的时尚是全年保持夏令时,最近由土耳其和摩洛哥完成,美国也即将采用这种方式。
So if you want an appointment or a task to be done at a certain time-of-day, you have represent that as a LocalDateTime
which represents a date and time-of-day without the context of an offset/zone, plus represent separately the intended time zone (ZoneId
).
因此,如果您希望在一天中的某个时间完成约会或任务,则将LocalDateTime
其表示为代表日期和时间的 a 没有偏移/区域的上下文,另外分别表示预期时区 ( ZoneId
)。
LocalDate ld = LocalDate.of( 2020 , Month.MARCH , 15 ) ;
LocalTime lt = LocalTime.of( 15 , 0 ) ;
LocalDateTime ldt = LocalDateTime.of( ld , lt ) ;
ZoneId z = ZoneId.of( "America/Thunder_Bay" ) ;
That code above describes when we intend something to occur, but cannot determine a moment. We do not know when 3 PM will happen on March 15, because the politicians controlling the America/Thunder_Bay
time zone may redefine the time zone at any moment. So all we can do is occasionally take a stab at it, dynamically. When you need to build a calendar, or schedule something to occur, you must apply the time zone to the LocalDateTime
(not a moment) to produce a ZonedDateTime
(a moment).
上面的代码描述了我们打算什么时候发生,但无法确定某个时刻。我们不知道 3 月 15 日下午 3 点是什么时候,因为控制America/Thunder_Bay
时区的政客随时可能重新定义时区。所以我们所能做的就是偶尔动态地尝试一下。当您需要构建日历或安排某事发生时,您必须将时区应用于LocalDateTime
(不是片刻)以生成ZonedDateTime
(片刻)。
ZonedDateTime zdt = ZonedDateTime.of( ldt , z ) ;
Instant instant = zdt.toInstant() ; // Adjust from zone to UTC (an offset of zero). Same moment, same point on the timeline.
Executors
执行者
To schedule your task to run, learn about the Executors frameworkbuilt into Java. Specifically, the ScheduledExecutorService
class.
要安排您的任务运行,请了解Java 中内置的Executors 框架。具体来说,ScheduledExecutorService
班级。
Firs calculate your elapsed time to wait until running the task.
首先计算您等待运行任务所用的时间。
Duration duration = Duration.between( Instant.now() , instant );
Define the task to be run as a Runnable
. Here we use modern lambda syntax, but that is beside the point.
将要运行的任务定义为Runnable
. 这里我们使用现代 lambda 语法,但这不是重点。
Runnable runnable = ( ) -> {
System.out.println( "Running our task now: " + Instant.now() );
};
Schedule your task to run. Optionally capture the returned ScheduledFuture
if you want to track completion.
安排您的任务运行。ScheduledFuture
如果您想跟踪完成情况,可选择捕获返回的内容。
final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture future = scheduler.schedule( runnable , duration.toMinutes() , TimeUnit.MINUTES );
Important: Be sure to gracefully shutdown your ScheduledExecutorService
. Otherwise, the thread pool may continue running, even after you end your program.
重要提示:请务必正常关闭您的ScheduledExecutorService
. 否则,线程池可能会继续运行,即使在您结束程序之后也是如此。