将日期转换为东部时间 - 获取日期对象作为输出

时间:2018-03-22 14:19:03

标签: java date timezone date-conversion java.util.date

我见过很多将日期从一个时区转换为另一个时区的例子。但是所有这些都输出为String。我想要一个日期对象作为输出。

我尝试过的方法 -

方法1

SimpleDateFormat dateTimeFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss a z");
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
Date date = new Date();

System.out.println(dateTimeFormat.format(date)); // this print IST Timezone

DateFormat timeFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss a z");
timeFormat.setTimeZone(TimeZone.getTimeZone("America/New_York"));

String estTime = timeFormat.format(date);
try {
    date = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss a z", Locale.ENGLISH).parse(estTime);
    System.out.println(date);

    } catch (ParseException ex) {
    Logger.getLogger(A.class.getName()).log(Level.SEVERE, null, ex);
}


System.out.println(timeFormat.format(date));

方法2

private static Date shiftTimeZone(Date date, TimeZone sourceTimeZone, TimeZone targetTimeZone) {
        System.out.println(sourceTimeZone.toString());
        System.out.println(targetTimeZone.toString());
        Calendar sourceCalendar = Calendar.getInstance();
        sourceCalendar.setTime(date);
        sourceCalendar.setTimeZone(sourceTimeZone);

        Calendar targetCalendar = Calendar.getInstance();
        for (int field : new int[]{Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND}) {
            targetCalendar.set(field, sourceCalendar.get(field));
        }
        targetCalendar.setTimeZone(targetTimeZone);

        return targetCalendar.getTime();
    }

方法1以字符串形式给出结果。

03/22/2018 10:16:57 AM EDT <- instanceOf String

方法2给出了东部时区时区的正确日期和时间,但是日期具有IST的时区。

Thu Mar 22 10:16:57 IST 2018 <- instanceof Date

任何人都可以帮我通过东部时间TimeZone获取Date对象。

更新 - 我的最终目标是获取当前东部时间的Unix时间戳。

1 个答案:

答案 0 :(得分:3)

TL;博士

Instant.now()                        // Capture the current moment in UTC, an `Instant` object.
    .atZone(                         // Adjust from UTC into a particular time zone.
        ZoneId.of( “Asia/Kolkata” ) 
    )                                // Returns a `ZonedDateTime` object. 
    .withZoneSameInstant(            // Adjust into yet another time zone. All three are the same moment but vowed using different wall-clock times. 
        ZoneId.of( “Africa/Tunis” ) 
    )                                // Returns another `ZonedDateTime` object. 

或者...

ZonedDateTime.now( 
    ZoneId.of( “Asia/Kolkata” )
).withZoneSameInstant(
    ZoneId.of( “Africa/Tunis” )
)

避免遗留日期时间类

首先,停止使用旧版日期时间类。他们是一个可怕的可怜的混乱。由 java.time 类取代。

  • Date已替换为Instant
  • Calendar已被ZonedDateTime
  • 取代
  • SimpleDateFormat已替换为DateTimeFormatter

Date::toString

欺骗

其次,要了解Date有一个非常令人困惑的特性,即在生成String时动态应用JVM的当前默认时区。 Date始终代表UTC中的一个时刻。 toString方法会产生Date携带时区的错误幻觉,而实际上其值为UTC。虽然班级设计师心地善意,但这是一个灾难性的决定,几十年来无数程序员的混乱也没有结束。

更糟糕的是:实际上埋藏在Date中的时区,但与此讨论无关。混乱?是;就像我说的那样,一个糟糕的糟糕设计。

Instant

替换Instant的{​​{1}}类更清晰。 Date表示时刻,时间轴上的点,始终为UTC,分辨率为纳秒。

使用Instant捕获UTC中的当前时刻。 JVM的当前默认时区是无关紧要的。主机OS分配的时区是无关紧要的。

Instant

Instant instant = Instant.now() ; // Capture the current moment in UTC. 不同,Date::toString方法说实话。 Instant::toString始终为UTC,因此Instant始终报告UTC。 String以标准ISO 8601格式生成。最后toStringZ的缩写,表示UTC。

  

instant.toString():2018-01-23T12:34:56.123456789Z

关于捕获当前时刻......在Java 8中,即使java.time类表示纳秒,当前时刻仍然以捕获。在Java 9及更高版本中,Zulu的新实现提供了以更精细的粒度捕获当前时刻。在macOS Sierra的Java 9.0.4中,我看到了微秒。现今传统计算机上的硬件时钟无法捕获当前时刻,精确度超过微秒。

Clock

要通过特定区域人员使用的挂钟时间镜头查看同一时刻,请指定该区域的时区。将ZonedDateTime应用于ZoneId会产生Instant。从概念上讲:

  

ZonedDateTime =(Instant + ZoneId)

在代码中:

ZonedDateTime

调整到另一个时区很容易。您可以再次从ZoneId z = ZoneId.of( “Pacific/Auckland” ) ; ZonedDateTime zdt = instant.atZone( z ) ; // Same moment, same point on the timeline, different wall-clock time. 开始。

Instant

或者您可以调整ZoneId zKolkata = ZoneId.of( “Asia/Kolkata” ) ; ZonedDateTime zdt = instant.atZone( zKolkata ) ; 对象。 java.time 类使用不可变对象。因此,调整不是“改变”(改变)原始对象,而是产生一个新的不同对象。

ZonedDateTime

您可以跳过使用ZonedDateTime zdtKolkata = zdt.withZoneSameInstant( zKolkata ) ; // Same moment, same point on the timeline, different wall-clock time. 。我不建议这样做。程序员应该在UTC中进行思考,调试,记录,交换数据以及他们的大部分业务逻辑。因此,只要您开始使用日期时间值,Instant就应该是您的首选课程。

Instant

ZonedDateTime zdtNewYork = ZonedDateTime.now( ZoneId.of( "America/New_York" ) ) ; 方法明智地扩展了ISO 8601标准,方法是在方括号中附加时区名称。

ZonedDateTime::toString
  

2018-01-23T07:34:56.123456789-05:00 [美国/纽约]

关于 java.time

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

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要String output = zdtNewYork.toString() ; 类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore