Java 将毫秒时间戳转换为相对于给定时区的日期

Java convert millisecond timestamp to date with respect to given timezone

我看过很多这方面的资源,但我无法得到的是在转换毫秒时间戳时,我如何在转换过程中添加相应的时区。

Date date = new Date(Long.valueOf(dateInMil*1000L);
SimpleDateFormat myDate = new SimpleDateFormat("EEE, MMM d, ''yy");
String formatted = myDate.format(date);

现在,如果我有 zone/offset 字符串形式的时间,即“-04:00”或“+2:00”,如何将它应用到上面以便我可以获得正确的日期?

不完全是您要找的东西,但很接近

String timeZone = "America/Los_Angeles"
TimeZone tz = TimeZone.getTimeZone(timeZone);
SimpleDateFormat sdf = new SimpleDateFormat("EEEEE MMMMM d hh:mm a");
sdf.setTimeZone(tz);

Date localizedTime = sdf.format(new Date());

如果您保留本地化字符串而不是偏移量,这将起作用。或者你可以制作一张地图。

我之前做过类似的事情project.You可以使用SimpleDateFormat的setTimeZone方法class。像这样:

mydate.setTimeZone(TimeZone.getTimeZone("GMT -0400"));

tl;博士

Instant.ofEpochMilli( myCountOfMilliseconds ) 
       .atZone( ZoneId.of( "Africa/Tunis" ) )
       .toString()

java.time

现代方法使用 java.time 类 而不是麻烦的旧方法 Calendar/Date 类 现在是遗留的。

假设您的毫秒计数是自 epoch reference of first moment of 1970 in UTC (1970-01-01T00:00) 以来的计数,然后解析为 Instant.

Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds(最多九 (9) 位小数)。

Instant instant = Instant.ofEpochMilli( myCountOfMilliseconds ) ;

UTC to another time zone, apply a ZoneId to get a ZonedDateTime 移动。

指定 proper time zone name in the format of continent/region, such as America/Montreal, Africa/CasablancaPacific/Auckland。切勿使用 ESTIST 等 3-4 字母缩写,因为它们 不是 真正的时区,未标准化,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

对象与文本

分配时区后,然后 生成所需格式的字符串(不是之前)。您可能将日期时间值(对象)与以文本方式表示其值的字符串混为一谈。学会思考智能对象,而不是愚蠢的字符串。

DateTimeFormatter

要生成特定格式的字符串,请使用 DateTimeFormatter. Search Stack Overflow as this been covered many many times, as have the other concepts shown here. Of special note are the DateTimeFormatter.ofLocalized… 方法。


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

java.time类在哪里获取?

  • Java SE 8, Java SE 9,及以后
    • 内置。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and Java SE 7
  • Android
    • Android java.time 类.
    • 捆绑实施的更高版本
    • 对于较早的 Android,ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

    DateTimeFormatter myDateFormatter
            = DateTimeFormatter.ofPattern("EEE, MMM d, ''yy", Locale.ENGLISH);
    long dateInSec = 1_554_321_098L;
    String utcOffsetString = "-04:00";
    ZoneOffset offset = ZoneOffset.of(utcOffsetString);
    String date = Instant.ofEpochSecond(dateInSec)
            .atOffset(offset)
            .format(myDateFormatter);
    System.out.println(date);

这会打印

Wed, Apr 3, '19

您给出的另一个示例偏移量 +2:00 稍微困难一些,因为 ZoneOffset.of 只需要小时数 (+2) 或冒号前的两位数小时数 (+02:00).一种解决方案是在将字符串传递给 ZoneOffset:

之前修复字符串
    String utcOffsetString = "+2:00";
    utcOffsetString = utcOffsetString.replaceFirst("([-+])(\d:\d{2})", "");
    ZoneOffset offset = ZoneOffset.of(utcOffsetString);

结果还是Wed, Apr 3, '19。如果字符串中已经有两位数的小时数,replaceFirst 将不会替换任何内容,因此您只会得到相同的字符串。

如果我将偏移量更改为 +08:00,我将得到 Thu, Apr 4, '19

编辑:坦率地说,我发现我用于修复偏移字符串的正则表达式非常难读。这是修复它的更简单方法:

    DateTimeFormatter offsetFormatter = DateTimeFormatter.ofPattern("O", Locale.ENGLISH);
    ZoneOffset offset = ZoneOffset.from(offsetFormatter.parse("GMT" + utcOffsetString));

像 Basil Bourque 我正在使用 java.time. See all the details in