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



我见过很多将日期从一个时区转换为另一个时区的例子。但它们都具有字符串输出。我想要一个日期对象作为输出。

我尝试过的方法 -

方法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

任何人都可以帮我获取东部时区的日期对象。

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

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有一个非常令人困惑的功能,即在生成字符串时动态应用 JVM 的当前默认时区。Date始终表示 UTC 中的时刻。toString方法会产生一种错误的错觉,即Date携带时区,而实际上其值采用 UTC 格式。虽然类设计者的意图是好的,但这是一个灾难性的决定,几十年来在无数程序员中造成了无休止的困惑。

更糟糕的是:Date中实际上埋藏着一个时区,但与本次讨论无关。混乱?是的;正如我所说,一个糟糕设计的可怕可怜的混乱。

Instant

取代DateInstant要清楚得多。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。概念:

分区日期时间 = ( 即时 + 区域 ID )

在代码中:

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[美国/New_York]


关于java.time

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

Joda-Time项目现在处于维护模式,建议迁移到 java.time 类。

要了解更多信息,请参阅Oracle 教程。并搜索堆栈溢出以获取许多示例和解释。规范为 JSR 310。

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

从哪里获得java.time类?

Java SE
  • 8Java SE 9及更高版本
    • 内置。
    • 具有捆绑实现的标准 Java API 的一部分。
    • Java 9添加了一些小功能和修复。
  • Java SE 6 和 Java SE 7 大部分
    • java.time 功能在ThreeTen-Backport中向后移植到 Java 6 和 7。
  • Android
    • 更高版本的 java.time 类的 Android 捆绑实现。
    • 对于早期的Android(<26),ThreeTenABP项目适应了ThreeTen-Backport(如上所述)。请参阅如何使用ThreeTenABP...

ThreeTen-Extra项目通过额外的类扩展了java.time。这个项目是未来可能添加到java.time的试验场。你可以在这里找到一些有用的类,如IntervalYearWeekYearQuarter等。

最新更新