我见过很多将日期从一个时区转换为另一个时区的例子。但是所有这些都输出为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时间戳。
答案 0 :(得分:3)
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格式生成。最后toString
是Z
的缩写,表示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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; SimpleDateFormat
现在位于Joda-Time的maintenance 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的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。