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

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

我已经看到了许多将日期从一个时区转换为另一个时区的示例。但是它们全部都以字符串形式输出。我想要一个日期对象作为输出。

我尝试过的方法-

方法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时间戳。

最佳答案

tl; dr

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方法的值实际上是UTC时,它会创建带有时区的Date错误假象。尽管是由类设计人员精心设计的,但这是一个灾难性的决定,数十年来,无数程序员之间的困惑一直没有结束。

更糟糕的是:Date中实际上埋藏有一个时区,但与该讨论无关。令人困惑?是;正如我所说,糟糕的设计糟透了。

Instant

替换InstantDate类更加清晰。 Instant代表时刻,即时间轴上的一个点,始终以UTC表示,分辨率为纳秒。

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

Instant instant = Instant.now() ;  // Capture the current moment in UTC. 


Date::toString不同,Instant::toString方法说的是事实。 Instant始终为UTC,因此toString始终报告UTC。字符串以标准ISO 8601格式生成。末尾的ZZulu的缩写,表示UTC。


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


关于捕获当前时刻…在Java 8中,即使java.time类可以表示纳秒,也以毫秒为单位捕获了当前时刻。在Java 9和更高版本中,Clock的新实现提供了更精细的捕获当前时刻的功能。在macOS Sierra上的Java 9.0.4中,我看到了微秒。如今,常规计算机上的硬件时钟无法以微秒为单位捕获当前时刻。

ZonedDateTime

要通过特定地区的人们使用的墙上时钟查看同一时刻,请分配该地区的时区。将ZoneId应用于Instant会生成ZonedDateTime。从概念上讲:


  ZonedDateTime =(即时+ ZoneId)


在代码中:

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 ) ;  


或者,您可以调整ZonedDateTime对象。 java.time类使用不可变的对象。因此,调整将产生一个新的独特对象,而不是“改变”(更改)原始对象。

ZonedDateTime zdtKolkata = zdt.withZoneSameInstant( zKolkata ) ;  // Same moment, same point on the timeline, different wall-clock time. 


您可以跳过Instant的使用。我不建议这样做。程序员应该在UTC中进行思考,调试,记录,数据交换以及许多业务逻辑。因此,每当使用日期时间值开始任何工作时,Instant应该是您的首选课程。

ZonedDateTime zdtNewYork = ZonedDateTime.now( ZoneId.of( "America/New_York" ) ) ;


ZonedDateTime::toString方法通过在方括号中添加时区名称来明智地扩展ISO 8601标准。

String output = zdtNewYork.toString() ;



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




关于java.time

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

现在位于Joda-Time中的maintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换java.time对象。使用与JDBC driver或更高版本兼容的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?


Java SE 8Java SE 9和更高版本


内置的
标准Java API的一部分,具有捆绑的实现。
Java 9添加了一些次要功能和修复。

Java SE 6Java SE 7


ThreeTen-Backport中的许多java.time功能都已反向移植到Java 6和7。

Android


更高版本的Android捆绑了java.time类的实现。
对于早期的Android(<26),ThreeTenABP项目改编了ThreeTen-Backport(如上所述)。请参见How to use ThreeTenABP…



ThreeTen-Extra项目使用其他类扩展了java.time。该项目是将来可能向java.time添加内容的试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

关于java - 将日期转换为东部时间-获取日期对象作为输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49431025/

相关文章:

java日期解析错误行为

java - 我可以强制 Java 忽略时区吗?

python - 从本地时区转换为 utc 时区

java - 对于在 Java/Swing 中创建流畅的动画来说,这是一个很好的设计吗?

java - Spring MVC中如何设置默认值来获取数组参数

精确到秒的 Javascript 模糊时间(例如 '10 minutes ago')

Java 转换时区

javascript - 将时间转换为时刻时区中的特定时区

java - Maven 依赖项 :get get LATEST ignore repositories from settings. xml

java - 无法使用 jsch 执行 sftp 子命令