我对Java的时区很好奇。我想从设备上获取以毫秒为单位的UTC时间并发送到服务器。服务器在向用户显示时间时会将其转换为本地时区。我系统中的时区是澳大利亚/悉尼(UTC 11:00),当我测试时区时,我得到了下面的结果:
int year = 2014;
int month = 0;
int date = 14;
int hourOfDay = 11;
int minute = 12;
int second = 0;
Calendar c1 = Calendar.getInstance();
c1.set(year, month, date, hourOfDay, minute, second);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss z");
System.out.println(sdf.format(c1.getTime()));
Calendar c2 = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
c2.set(year, month, date, hourOfDay, minute, second);
System.out.println(sdf.format(c2.getTime()));
输出:
14/01/2014 11:12:00 EST
14/01/2014 22:12:00 EST
我以为我可以有 13/01/2014 00:12:00 对于 c2,因为 UTC 时间比我的晚 11 小时。日历没有按照我预期的方式工作吗?
非常感谢你的帮助。
添加z以显示时区。这让我更加困惑,因为Mac说它的时区是(AEDT)澳大利亚东部夏令时,但Java是EST。无论如何,结果还是不同的,因为EST是UTC-5小时。
使用现代 java.time 类。
ZonedDateTime
.of( 2014 , 1 , 14 , 11 , 12 , 0 , 0 , ZoneId.of( "Australia/Sydney" ) )
.toInstant()
.toEpochMilli()
1389658320000
走向另一个方向。
Instant
.ofEpochMilli( 1_389_658_320_000L ) // .toString(): 2014-01-14T00:12:00Z
.atZone(
ZoneId.of( "Australia/Sydney" )
) // .toString(): 2014-01-14T11:12+11:00[Australia/Sydney]
.format(
DateTimeFormatter
.ofPattern (
"dd/MM/uuuu HH:mm:ss z" ,
new Locale( "en" , "AU" )
)
)
14/01/2014 11:12:00 AEDT
您正在使用糟糕的日期-时间类,由于采用了定义现代java.time类的JSR 310,这些类已经过时了。
我对Java的时区很好奇。
仅供参考,UTC 的偏移量只是小时-分钟-秒的数量。当我们说“UTC”或在字符串末尾放置 Z
时,我们的意思是 UTC 本身的零小时-分钟-秒的偏移量。
时区远不止如此。时区是特定地区的人们使用的时差的过去、现在和未来变化的历史。世界各地的政治家们都有一种奇怪的偏好,那就是改变他们管辖权的偏移。
我想从一个设备获取UTC时间(以毫秒为单位),并发送给服务器。
对于当前时刻,请使用即时
。内部的Instant
是自1970 UTC第一时刻的历元参考起的整秒秒数,加上以纳秒为单位的几分之一秒。
Instant now = Instant.now() ; // Capture current moment in UTC.
long millisecondsSinceEpoch = now.toEpochMilli() ;
走向另一个方向。
Instant instant = Instant.ofEpochMilli( millisecondsSinceEpoch ) ;
服务器将其转换为本地时区…
指定用户期望的时区。
如果没有指定时区,JVM将隐式应用其当前的默认时区。该默认值可能会在运行时的任何时刻发生变化。),因此您的结果可能会有所不同。最好将您想要/预期的时区明确指定为一个参数。如果非常重要,请与您的用户确认该区域。
以大陆/地区格式指定正确的时区名称,例如美洲/蒙特利尔
、非洲/卡萨布兰卡
或太平洋/奥克兰
。切勿使用 2-4 个字母的缩写,例如
EST
或 IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
…当它向用户显示时间时
针对用户的语言和文化自动本地化。
要本地化,请指定:
FormatStyle
确定字符串的长度或缩写。 < li>
区域设置
来确定: < ul > < li >用于翻译日期名称、月份名称等的人类语言。 < li >决定缩写、大写、标点、分隔符等问题的文化规范。
例:
Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.JAPAN, etc.
DateTimeFormatter f =
DateTimeFormatter
.ofLocalizedDateTime( FormatStyle.FULL )
.withLocale( l )
;
String output = zdt.format( f );
我的系统中的时区是澳大利亚/悉尼(UTC 11:00)
服务器的当前默认时区应该与程序无关。始终指定所需/预期的时区。坦率地说,使各种日期-时间方法的时区(和Locale
)参数可选是java.time框架中为数不多的设计缺陷之一。
提示:通常最好将您的服务器设置为UTC作为其当前默认时区。
顺便说一句,要清楚时区和地区是没有任何关系的。您可能希望用日语显示在< code >非洲/突尼斯时区看到的时刻。
ZoneID zAuSydney = ZoneId.of( "Australia/Sydney" ) ;
ZonedDateTime zdt = instant.atZone( zAuSydney ) ;
String output = zdt.format(
DateTimeFormatter
.localizedDateTime( FormatStyle.LONG )
.withLocale( new Locale( "en" , "AU" ) ;
) ;
int year = 2014…
请注意java。与传统类不同,time使用理智的编号。一月至十二月的月份为1-12,周一至周日的工作日为1-7。
LocalDate ld = LocalDate.of( 2014 , 1 , 14 ) ;
LocalTime lt = LocalTime.of( 11 , 12 ) ;
ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
zdt.toString() = 2014-01-14T11:12 11:00[澳大利亚/悉尼]
如上所述,通常最好自动本地化显示。但如果你坚持,你可以硬编码一个格式化模式。
Locale locale = new Locale ( "en" , "AU" );
ZoneId z = ZoneId.of ( "Australia/Sydney" );
ZonedDateTime zdt = ZonedDateTime.of ( 2014 , 1 , 14 , 11 , 12 , 0 , 0 , z );
zdt。toString():2014-01-14T11:12 11:00[澳大利亚/悉尼]
指定您的格式模式。
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "dd/MM/uuuu HH:mm:ss z" , locale );
String output = zdt.format ( f );
输出=2014年1月14日11:12:00 AEDT
你的问题感兴趣的是从1970-01-01T00:00:00Z开始的毫秒计数。因此,请从澳大利亚时区调整为UTC。同一时刻,时间线上的同一点,不同的挂钟时间。
Instant instant = zdt.toInstant() ; // Adjust from time zone to UTC.
instant . tostring():2014-01-14t 00:12:00Z
请注意即时
和zdt
我想我可以有13/01/2014 00:12:00为c2因为UTC时间是11小时晚于我的。
➥ 正如您所要求的,悉尼地区上午11点后12分钟与UTC午夜12分钟相同,因为澳大利亚/悉尼
在该日期比UTC提前11小时。
计算自纪元以来的毫秒数。
long millisecondsSinceEpoch = instant.toEpochMilli() ;
你可能想在你的格式化程序上设置时区,而不是日历(或者除了日历之外,并不是100%清楚你想完成什么)!用于创建人类表示的时区来自SimpleDateFormat。当您通过调用< code>getTime()将日历转换回java.util.Date时,日历中的所有“时区”信息都将丢失。
代码:
Calendar c2 = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
c2.set(year, month, date, hourOfDay, minute, second);
System.out.println(sdf.format(c2.getTime()));
正在打印 14/01/2014 10:12:00
,因为 Syndey(格式化程序的时区)中显示的 11AM UTC 是晚上 10 点!(在格式中使用 HH 表示 24 小时制)
这会打印出你想做的事情:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss z");
System.out.println(sdf.format(c1.getTime()));
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(sdf.format(c1.getTime()));
“UTC 毫秒”的概念毫无意义。毫秒的数量只是历史中的一个固定点,它没有与之关联的时区。我们为其添加一个时区,以将其转换为人类可读的表示形式。
编辑:是的,对(美国)东部时间和(澳大利亚)东部时间同时使用“EST”的歧义一直是Java的一个陷阱。
更新:此答案现已过时。Joda-Time 库现在被 Java 8 及更高版本中内置的 java.time 框架所取代。请参阅此新答案。
您应避免使用3或4个字母的时区代码,如EST
或IST
。它们既不是标准的,也不是独一无二的。
使用正确的时区名称,主要是大陆/城市或地区
,如美洲/蒙特利尔
或亚洲/加尔各答
。
java.util.日期/日历类是出了名的糟糕。避免使用它们。使用Joda-Time,或者在Java8中,使用由JSR 310定义并受Joda-Time启发的新java.time.*类。
请注意,下面显示的Joda Time代码更简单、更明显。Joda Time甚至知道如何计数——
在Joda-Time中,DateTime实例知道自己的时区。
澳大利亚悉尼的标准时间比UTC/GMT提前10小时,夏令时(DST)提前11小时。DST适用于问题指定的日期。
提示:不要这样想...
UTC时间比我晚11小时
这样想…
悉尼DST比UTC/GMT早11个小时。
如果您用UTC/GMT思考、工作和存储,日期-时间工作会变得更容易,更不容易出错。仅转换为本地化的日期时间,以便在用户界面中显示。全球思考,局部展示。您的用户和服务器可以很容易地转移到其他时区,所以忘记您自己的时区。始终指定一个时区,不要假设或依赖默认值。
下面是一些使用Joda-Time 2.3和Java 8的示例代码。
// Better to specify a time zone explicitly than rely on default.
// Use time zone names, not 3-letter codes.
// This list is not quite up-to-date (read page for details): http://joda-time.sourceforge.net/timezones.html
DateTimeZone timeZone = DateTimeZone.forID("Australia/Sydney");
DateTime dateTime = new DateTime(2014, 1, 14, 11, 12, 0, timeZone);
DateTime dateTimeUtc = dateTime.toDateTime(DateTimeZone.UTC); // Built-in constant for UTC (no time zone offset).
转储到控制台…
System.out.println("dateTime: " + dateTime);
System.out.println("dateTimeUtc: " + dateTimeUtc);
运行时…
dateTime: 2014-01-14T11:12:00.000+11:00
dateTime in UTC: 2014-01-14T00:12:00.000Z
问题内容: 我对Java中的时区感到好奇。我想从设备获取UTC时间(以毫秒为单位)并发送到服务器。当服务器向用户显示时间时,服务器会将其转换为本地时区。我系统中的时区是澳大利亚/悉尼(UTC + 11:00),测试时区时,我得到的结果如下: 输出: 我以为我可以为c2安排13/01/2014 00:12:00,因为UTC时间比我的时间晚11个小时。日历不能按我期望的方式工作吗? 您的帮助将不胜感激
问题内容: 我知道这个主题已被殴打致死,但在搜寻了这个问题几个小时之后,我不得不问。 我的问题:根据客户端应用程序(iphone)的当前时区对服务器上的日期进行计算。客户端应用程序以秒为单位告诉服务器,其时区距GMT的距离。然后,我想使用此信息对服务器中的日期进行计算。服务器上的日期都存储为UTC时间。 因此,在将UTC日期对象转换为该本地时区之后,我想获取其HOUR。 我目前的尝试: 变量小时和
问题内容: 我有一个UTC时区,例如: 还有一个pytz时区对象: 转换为给定时区的正确方法是什么? 问题答案: 我想我明白了: 这行代码首先将朴素的(不了解时区的) 对象转换为包含时区(UTC)的对象。然后,它使用该功能根据请求的时区调整时间。
问题内容: 如何将UTC时间转换为 当地时间 ? 我已经为我需要当地时间的所有国家/地区创建了具有UTC时差的地图。然后,我将该差异作为持续时间添加到当前时间(UTC),并打印结果希望是该特定国家/地区的当地时间。 由于某些原因,结果是错误的。例如,在匈牙利,相差一小时。知道为什么我得到的结果不正确吗? 问题答案: 请记住,操场的时间设置为,因此它正在工作。 正确的方法是使用,这是一个示例:
问题内容: 我有一个毫秒本地本地时间戳,我想将其转换为毫秒本地UTC时间戳。快速浏览一下文档,看起来像这样工作: 有一个更好的方法吗? 问题答案: 使用a 来获取本地纪元处的偏移量,然后将其添加到本地纪元时间戳中。
我们在本地时区(如EST、PST、CST等)的sql中有多列。我们希望将UTC时区中的所有这些时区转换为考虑到日光节省并将其保存到另一列。 我尝试了下面的查询,但它将UTC转换为当地时区(EST ),但我正在寻找EST到UTC时区。 选择CONVERT(日期时间,SWITCHOFFSET(日期时间字段,日期部分(TZOFFSET,时间区域“东部标准时间”的日期时间字段))