我是java的新手,因此很长一段时间都无法解决这个问题。
我使用的是Windows XP,机器设置为TimeZone:东部时间(美国和加拿大)。
我有一个Java应用程序,该应用程序获取当前系统时间和时区信息,并将如下字符串:20101012 15:56:00 EST写入文件。
上面的最后一段日期,即:时区,随着我改变系统日期,从EST变为EDT。
准确:从11月(例如:2009年11月)到3月(2010年3月),它是EST,否则是EDT。
EST是我想要的 总是 而不是EDT。
是否有任何特定的类/功能,我总是可以将其读作EST?
等待回复。
感谢您的回复。 好吧,我忘了提几件事。
我希望我的机器在Windows时区设置中设置为:东部时间(美国和加拿大)。
简单来说,我想做的是:获取机器时间,并将其写入文本文件
我知道从3月到11月的夏令时。
但问题是,当我将机器时间写入文件时,如果夏令时(DST)不存在,则写为2010 01 12 15:56:00美国东部时间,20101012 15:56:00美国东部时间,如果存在DST。 我担心的是,无论是否是夏令时,我都想写EST。
答案 0 :(得分:3)
我认为你不应该按照你的意思行事。
您说的是,无论您的系统时区当前是什么(东部时间不是您的时区,但UTC + 5或+4是),您希望它显示EST。这显然是错误的。假设它是在夏天,你的电脑认为它是在本地的2010/6/15 15:00。您打印当前时间,然后得到:
我打印出来的时间是:2010 06 15 15:00:00美国东部时间
无论出于何种原因,您认为EDT令人不快,因此您将其更改为EST:
我打印出来的时间是:2010 06 15 15:00:00 EST
然而,如果你在接下来的一小时内将该片段发送给其他人,他们将被迫认为你是从未来走过的!美国东部时间15:00:00是美国东部时间16:00:00。
答案 1 :(得分:2)
我会创建一个自定义区域:
TimeZone alwaysEst = TimeZone.getTimeZone("EST+5");
那将报告为EST,并且将始终比UTC早5个小时。特别是,不要选择现有的时区,否则当区域更新更改定义时最终会被刻录。
请注意,通过强制EST,您记录的日期将仅匹配系统在一年中的5个月显示的时间。其他7个月你将休息一小时。它可以简化解析文件,但会使用户感到困惑。
答案 2 :(得分:2)
我是Java的新手,因此很长一段时间以来一直无法弄清这一点。
即使是有经验的程序员,日期时间处理也非常棘手。这些概念很滑。各行各业的人们已经开发出各种实践,从而使事情变得复杂。
幸运的是,Java现在内置了业界领先的日期时间工作框架:JSR 310中定义的 java.time 。
我正在使用Windows XP,并且机器设置为TimeZone:
主机操作系统不应影响您使用Java进行日期时间处理的工作。
从不依赖主机的当前默认时区。该默认值可以随时更改,因此它是程序员无法控制的。相反,请在Java代码中指定所需/期望的时区。
ZoneId z = ZoneId.of( "America/New_York" ) ;
EDT
/ Eastern Time
不是时区...东部时间(美国和加拿大)。
实际上没有“东部时间”这样的东西。这个不精确的术语是一个抓包集体名词,用于描述各个时区使用的当前UTC偏移量。进行编程时,请忘记“ Eastern Time”,“ EST”和其他伪区域。
了解偏移量仅在本初子午线之前或之后数小时-数分钟-秒。偏移量看起来像+05:30
或-05:00
。
时区远不止于此。时区是过去,现在和将来更改特定区域的人们使用的偏移量的历史。时区的规则是政客反复设定的,并且以惊人的频率变化。
正确的时区名称由Continent/Region
组成,例如America/Montreal
或America/New_York
。请参阅this list of zones at Wikipedia(可能不是最新的)。
将类似:20101012 15:56:00 EST的字符串写入文件。
我们有一个正式的国际标准,用于将日期时间值的格式序列化为文本:ISO 8601。不要自己发明!标准格式经过精心设计,具有实用性,易于通过机器解析以及易于跨文化的人阅读的特点。
例如,2010年10月12日在魁北克,将近下午4点是:
2010-10-12T15:56-04:00
当parsing / generating为文本时, java.time 类默认使用ISO 8601格式。因此,无需指定格式化模式。使用ZonedDateTime
代表在特定时区看到的时刻。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2010 , 10 , 12 , 15 , 56 , 0 , 0 , z ) ;
ZonedDateTime::toString
方法明智地扩展了标准格式,以将区域名称附加在方括号中。
zdt.toString():2010-10-12T15:56-04:00 [美国/蒙特利尔]
解析这样的字符串。
ZonedDateTime zdt2 = ZonedDateTime.parse( "2010-10-12T15:56-04:00[America/Montreal]" ) ;
boolean sameZdts = zdt.equals ( zdt2 ) ;
sameZdts:是
看到那个code run live at IdeOne.com。
EST是我一直想要的,而不是EDT。
您的目标没有道理。
这些伪区域(EST
和EDT
旨在指示Daylight Saving Time (DST)何时生效以及标准时间何时生效。因此,要始终在遵守DST的区域(时区)中使用标准时间是一个矛盾,而且不可能。
因此,如果您要表示某个特定区域(时区)的人们所使用的挂钟时间所代表的时刻,则应指定日期,日期和时间通过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 [美国/纽约]
要在UTC中查看同一时刻,请提取Instant
。同一时刻,时间轴上的同一点,不同的时钟时间。
Instant instant = zdt.toInstant() ;
instant.toString():2010-10-12T19:56:00Z
请参见run live at IdeOne.com上方的代码。
我正在与一台服务器联系,我需要告诉它:“在xxx的20101015 15:30:30做一个任务” xxx是时区。无论何时,该服务器仅了解EST,而不了解EDT。因此,EDT令人不快。
关于EST与EDT,我们已经将您的担忧视为毫无意义/无关紧要。当特定时区切入DST或从DST切入时,这些标准时间与夏令时的标记会自动切换。
关于将来预约,您不知道夏令时(DST)是否有效。您不知道是否对您的时区规则做了一些 other 古怪的调整。
如上所述,时区定义由反复无常的政客控制。在世界各地,他们对频繁的更改表现出了惊人的喜好。在过去的几十年中,美国多次更改了DST转换日期。近年来,俄罗斯多次采用和降低DST。最新的流行趋势是全年保持DST不变,最近由土耳其和摩洛哥进行,而美国也处于这种趋势。
因此,如果您希望在一天的某个特定时间完成约会或任务,则可以将其表示为LocalDateTime
,它表示一天中的日期和时间,而没有上下文偏移量/时区,加号分别代表预期的时区(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" ) ;
上面的代码描述了我们何时打算发生某件事,但无法确定时刻。我们不知道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.
要安排任务运行,请了解Java内置的Executors framework。具体来说,是ScheduledExecutorService
类。
燃料费会计算出您等待运行任务所需的时间。
Duration duration = Duration.between( Instant.now() , instant );
定义要作为Runnable
运行的任务。在这里,我们使用现代的lambda语法,但这并不重要。
Runnable runnable = ( ) -> {
System.out.println( "Running our task now: " + Instant.now() );
};
安排任务运行。如果您想跟踪完成情况,则可以选择捕获返回的ScheduledFuture
。
final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture future = scheduler.schedule( runnable , duration.toMinutes() , TimeUnit.MINUTES );
重要提示:请确保正常关闭ScheduledExecutorService
。否则,即使您结束程序,线程池也可能继续运行。
答案 3 :(得分:0)
应该注意的是,在东部时区的夏季,几乎每个主要中心都使用夏令时,因此您可以正确地显示该时区的人们关心的时间。
如果您希望它是特定时区而不是默认/系统时区,那么您可以通过以下方式强制TimeZone到EST:
TimeZone est = TimeZone.getTimeZone("EST");
虽然正如迈克尔上面提到的那样,文档建议使用本地全名,例如“America / New York”而不是一般的时区缩写。
如果您想声称它确实是EST,即使您知道它是EDT,那么我想您可以执行以下操作:使用SimpleDateFormat
实例,其自定义模式不包含时区信息,然后将“EST”添加到您写出的字符串的末尾。
答案 4 :(得分:0)
你的问题仍然不明确。
如果您只是想强制'EST'字符,即使您的机器设置为自动切换DST,或者您想要获得EST上的实际时间,我也没有理解。
所以你有两个选择:
您的机器时间设置为下午2:15且DST开启,并且您希望在美国东部时间下午2:15(这不是正确的实际时间)写下您应该使用SimpleDateFormat。这样,你就会撒谎。但是,无论如何,你知道什么最适合你。
你的机器时间设置为下午2:15,DST开启,你想写东部时间下午1:15,你应该使用:TimeZone.setDefault(TimeZone.getTimeZone(“EST”))
答案 5 :(得分:0)
解决方案取决于你为什么要写这个时间以及你在阅读时想要用它做什么(它将用于做什么,而不是“你想要什么”)。总是把它写成EST是对事实的误解。当EDT生效时,不,实际上是EST。如果您尝试跟踪某些“绝对”时间点,我建议您使用 GMT 而不是任何时区。
答案 6 :(得分:-1)
将机器设置为TimeZone: 东部时间(美国和加拿大)。
这不是一个真正的时区(EDT和EST都不是)。时区(如Java所理解的)类似于“America / Phoenix”,它是管理时区的ID,它具有基本偏移和(可选)切换到特定日期的夏令时。这两种情况都可能发生变化,在解释历史日期时有必要考虑这些变化。
因此,如果您不想使用DST开关,请选择不遵守DST的时区。可能没有这样的时区,并试图采取行动,因为会引入不可能的日期。