我已经看到了许多将日期从一个时区转换为另一个时区的示例。但是它们全部都以字符串形式输出。我想要一个日期对象作为输出。
我尝试过的方法-
方法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
替换
Instant
的Date
类更加清晰。 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格式生成。末尾的Z
是Zulu
的缩写,表示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.Date
,Calendar
和SimpleDateFormat
。现在位于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 8,Java SE 9和更高版本
内置的
标准Java API的一部分,具有捆绑的实现。
Java 9添加了一些次要功能和修复。
Java SE 6和Java 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添加内容的试验场。您可能会在这里找到一些有用的类,例如
Interval
,YearWeek
,YearQuarter
和more。
关于java - 将日期转换为东部时间-获取日期对象作为输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49431025/