使用Calendar对象将时区从EEST更改为HST会意外更改时间 [英] Changing time zone with Calendar object from EEST to HST changes the time-of-day unexpectedly

查看:65
本文介绍了使用Calendar对象将时区从EEST更改为HST会意外更改时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些 TimeStamp ,并且日期格式为"EEEE,MMM dd,yyyy hh:mm a zzz" .但是我不知道如何显示带有时区的时间戳.当我尝试显示它时,我得到了错误的DateTime或错误的时区

I have some TimeStamp and I have date format "EEEE, MMM dd, yyyy hh:mm a zzz". But I don't know how I can show this timestamp with timezone. When I trying to show it I get wrong DateTime or wrong timezone

example1:

Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date(device.getUpdatedDate().getTime())); // here is 2018-07-09 20:02:26.506000
SimpleDateFormat sdf = new SimpleDateFormat(EMAIL_DATE_FORMAT);
sdf.format(calendar.getTime()); // i have wrong timezone

我得到美国东部时间2018年7月9日星期一晚上08:02

但是当我添加 sdf.setTimeZone(TimeZone.getTimeZone("HST")); 时,我有正确的时区和错误的时间 HST星期一,2018年7月9日上午7:02

but when i add sdf.setTimeZone(TimeZone.getTimeZone("HST")); i have right timezone and wrong time Monday, Jul 09, 2018 07:02 AM HST

预期结果 HST星期一,2018年7月9日晚上08:02

实际结果:美国东部时间2018年7月9日星期一晚上08:02 HST,2018年7月9日,星期一,07:02

推荐答案

tl; dr

  • 您看到的是功能,而不是错误,它会将同一时刻调整为另一个时区.
    • 东欧的晚上8点和夏威夷的早上7点.
    • tl;dr

      • You are seeing a feature, not a bug, adjusting same moment to another time zone.
        • 8 PM in eastern Europe is also 7 AM in Hawaii.
        • 您从UTC提前3小时的一个时区调整为UTC落后10小时的另一个时区,总共相差13小时.知道一个地方的8 PM同时在另一个地方的7 AM.

          You adjusted from one time zone 3 hours ahead of UTC to another zone 10 hours behind UTC, for a total difference of 13 hours. Understand that 8 PM in one place is simultaneously 7 AM in the other.

          请注意我们在以下代码中对 withZoneSameInstant ("Instant")的调用.

          Note our call to withZoneSameInstant (‘Instant’) in the following code.

          ZonedDateTime.of( 
              2018 , 7 , 9 , 20 , 2 , 0 , 0 , ZoneId.of( "Europe/Athens" )  // 8 PM in Greece.
          )
          .withZoneSameInstant(                                             // Adjust into another time zone to view the same moment with another wall-clock time.
              ZoneId.of( "Pacific/Honolulu" )                               // 7 AM in Hawaii.
          )
          .toString()
          

          2018-07-09T07:02-10:00 [太平洋/火奴鲁鲁]

          2018-07-09T07:02-10:00[Pacific/Honolulu]

          不同时刻:使用

          调用

          显然,您想要一个不同的时刻,时间轴上的一个不同的点,它具有相同的日期和一天中的时间,但是具有不同的时区.

          Different moment: Call withZoneSameLocal

          Apparently you wanted a different moment, a different point on the timeline, that has the same date and same time-of-day but a different time zone.

          请注意以下代码中对 withZoneSameLocal ("Local",而不是"Instant")的调用.

          Note our call to withZoneSameLocal (‘Local’, not ‘Instant’) in the following code.

          ZonedDateTime.of( 
              2018 , 7 , 9 , 20 , 2 , 0 , 0 , ZoneId.of( "Europe/Athens" )  // 8 PM in Greece.
          )
          .withZoneSameLocal(                                               // Different moment, coincidentally having the same date and same time-of-day. But different time zone means this is a different point on the timeline.
              ZoneId.of( "Pacific/Honolulu" )                               // Also 8 PM in Hawaii, which happens many hours later than 8 PM in Greece. Different moment, same wall-clock time.
          )
          .toString()
          

          2018-07-09T20:02-10:00 [太平洋/火奴鲁鲁]

          2018-07-09T20:02-10:00[Pacific/Honolulu]


          详细信息

          实时时区

          HST & EEST 是伪区域,不是实时区域.避免使用这3-4个字母代码,因为它们不是标准化的,甚至也不是唯一的(!).


          Details

          Real time zone

          HST & EEST are pseudo-zones, not real time zones. Avoid these 3-4 letter codes as they are not standardized and are not even unique(!).

          使用 tzdata 中定义的实时区域名称 IANA .请参阅Wikipedia中的列表(可能已过时).这些名称采用 Continent/Region (洲/地区)格式,例如 America/Montreal (美国/蒙特利尔)或 Europe/Tallinn (欧洲/塔林).

          Use real time zone names as defined in tzdata by the IANA. See a list in Wikipedia (possibly outdated). These names are in Continent/Region format such as America/Montreal or Europe/Tallinn.

          ZoneId z = ZoneId.of( "Europe/Vilnius" ) ;
          

          避免使用旧的日期时间类

          避免麻烦的类 Calendar & SimpleDateFormat .这些在几年前被 java.time 类所取代.使用 java.time 更加清晰和容易.

          Avoid legacy date-time classes

          Avoid the terribly troublesome classes Calendar & SimpleDateFormat. These were supplanted years ago by the java.time classes. Working with java.time is much clearer and easier.

          让我们开始吧.我想通过 EEST 可以想到一个东欧时区.我可以随意选择一个.

          Let's get your starting point. I am guessing that by EEST you had in mind one of the eastern European time zones. I am choosing one arbitrarily.

          ZoneId zAthens = ZoneId.of( "Europe/Athens" ) ;
          LocalDate ld = LocalDate.of( 2018 , Month.JULY , 9 ) ;  // 2018-07-09.
          LocalTime lt = LocalTime.of( 20 , 2 ) ;  // 8:02 PM.
          ZonedDateTime zdtAthens = ZonedDateTime.of( ld , lt , zAthens ) ;
          

          生成表示该String ="nofollow noreferrer"> ZonedDateTime 对象.默认情况下,明智地使用标准的 ISO 8601 格式,以将时区的名称添加为正方形括号.

          Generate a String representing the value of that ZonedDateTime object. By default, use standard ISO 8601 format wisely extended to append the name of the time zone in square brackets.

          String outputAthens = zdtAthens.toString() ;  // Generate `String` in a format extending standard ISO 8601 format.
          

          2018-07-09T20:02 + 03:00 [欧洲/雅典]

          2018-07-09T20:02+03:00[Europe/Athens]

          通过 HST ,我想你是说夏威夷时间.该区域的专有名称是 Pacific/Honolulu .

          By HST I guess you mean Hawaii time. The proper name for that zone is Pacific/Honolulu.

          ZoneId zHonolulu = ZoneId.of( "Pacific/Honolulu" ) ;
          

          让我们将雅典的时刻调整到夏威夷的另一个区域.时间轴上的相同时刻,相同点,但挂钟时间不同.想象一下,每个地方都有一对朋友打电话给他们,同时抬头看着他们墙上的时钟.每个人看到的是不同的时间,可能还有不同的日期,尽管如此,他们在时间轴上遇到的是同一时刻,同一时间点.

          Let's adjust our Athens moment into this other zone for Hawaii. Same moment, same point on the timeline, but a different wall-clock time. Imagine a pair of friends in each place calling each and simultaneously looking up at a clock on their wall. Each sees a different time-of-day and possibly a different date, nevertheless they experience the same simultaneous moment, same point on the timeline.

          ZonedDateTime zdtHonolulu = zdtAthens.withZoneSameInstant( zHonolulu ) ;  // Same moment (same `Instant` inside the `ZonedDateTime`) but a different time zone.
          

          那一天,檀香山比世界标准时间晚10个小时,而雅典比世界标准时间早3个小时.那是总共十三个小时的增量.因此,晚上8点(20:00)减去13是早上7点.我们希望在夏威夷看到早上7点.让我们通过生成另一个ISO 8601格式的字符串来进行验证.

          On that date, Honolulu is ten hours behind UTC while Athens is three hours ahead. That is a total delta of thirteen hours. So, 8 PM (20:00) minus 13 is 7 AM. We expect to see 7 AM in Hawaii. Let's verify, by generating another string in ISO 8601 format.

          String outputHonolulu = zdtHonolulu.toString() ;  // Generate `String` representing the value of the `ZonedDateTime` object.
          

          2018-07-09T07:02-10:00 [太平洋/火奴鲁鲁]

          2018-07-09T07:02-10:00[Pacific/Honolulu]

          果然,早上7点.

          也许您想要的是位于夏威夷的相同日期和同一时间.这意味着您代表同一时刻.您将在时间轴上代表另一个时间点,相差几个小时.

          Perhaps what you wanted was the same date and same time-of-day located in Hawaii. This would mean you are not representing the same simultaneous moment. You would be representing a different point on the timeline, off by several hours.

          ZonedDateTime 确实提供了此功能.在概念上调用 ZonedDateTime :: withZoneSameLocal 含义:使用相同的内部 LocalDate 和相同的内部 LocalTime ,但使用不同的分配的 ZoneId .

          The ZonedDateTime does provide for this function. Call ZonedDateTime::withZoneSameLocal meaning conceptually: Use the same internal LocalDate and the same internal LocalTime, but use a different assigned ZoneId.

          ZonedDateTime eightPmOnJuly9InPacificHonolulu = zdtAthens.withZoneSameLocal( zHonolulu) ; 
          String outputDifferentMoment= eightPmOnJuly9InPacificHonolulu.toString() ;
          

          2018-07-09T20:02-10:00 [太平洋/火奴鲁鲁]

          2018-07-09T20:02-10:00[Pacific/Honolulu]

          UTC

          所有在时区之间翻转的现象都会使人变得生气.通过专注于UTC来扎根.将UTC视为一个真实的时间,所有其他区域仅是变化而已.

          UTC

          All this flipping around between time zones can drive a person batty. Get grounded by focusing on UTC. Think of UTC as The One True Time, and all other zones are but mere variations.

          要从时区调整为UTC,请从我们的 ZonedDateTime 对象中提取一个 Instant 对象.根据定义, Instant 始终使用UTC.

          To adjust from a time zone to UTC, extract a Instant object from our ZonedDateTime objects. An Instant is always in UTC by definition.

          Instant instantAthens = zdtAthens.toInstant() ;
          Instant instantHonolulu = zdtHonolulu.toInstant() ;
          Instant instantDifferentMoment = eightPmOnJuly9InPacificHonolulu.toInstant() ;
          

          2018-07-09T17:02:00Z

          2018-07-09T17:02:00Z

          2018-07-09T17:02:00Z

          2018-07-09T17:02:00Z

          2018-07-10T06:02:00Z

          2018-07-10T06:02:00Z

          最后的 Z 表示UTC,发音为 Zulu ,并由ISO 8601和其他标准定义.

          The Z on the end means UTC, is pronounced Zulu, and is defined by ISO 8601 and other standards.

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

          The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

          Joda-Time 项目,现在位于<一个href ="https://en.wikipedia.org/wiki/Maintenance_mode" rel ="nofollow noreferrer">维护模式,建议迁移到要了解更多信息,请参见 Oracle教程.并在Stack Overflow中搜索许多示例和说明.规范为 JSR 310 .

          To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

          您可以直接与数据库交换 java.time 对象.使用符合 JDBC驱动程序/jeps/170"rel =" nofollow noreferrer> JDBC 4.2 或更高版本.不需要字符串,不需要 java.sql.* 类.

          You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

          在哪里获取java.time类?

          Where to obtain the java.time classes?

          • Later versions of Android bundle implementations of the java.time classes.
          • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

          > ThreeTen-Extra 项目扩展了java.time与其他班级.该项目为将来可能在java.time中添加内容提供了一个试验场.您可能会在这里找到一些有用的类,例如 间隔 年周" YearQuarter 更多

          这篇关于使用Calendar对象将时区从EEST更改为HST会意外更改时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆