简体   繁体   English

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

[英]Java convert millisecond timestamp to date with respect to given timezone

I have seen many resources on this but one thing I cant get is when converting the millisecond timestamp, how I add a corresponding time zone, during the conversion process. 我已经看到了很多这方面的资源,但我无法得到的一件事是转换毫秒时间戳,我在转换过程中如何添加相应的时区。

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

Now if I have a time zone/offset in string formate ie "-04:00" or "+2:00" how to apply it to the above so I can get the proper date ? 现在,如果我在字符串格式中有时区/偏移量,即“-04:00”或“+2:00”如何将其应用于上面,那么我可以得到正确的日期?

tl;dr TL;博士

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

java.time java.time

The modern approach uses the java.time classes rather than the troublesome old Calendar / Date classes that are now legacy. 现代方法使用java.time类,而不是现在遗留的麻烦的旧Calendar / Date类。

Assuming your count of milliseconds is a count since the epoch reference of first moment of 1970 in UTC (1970-01-01T00:00), then parse as a Instant . 假设您的毫秒计数是自UTC 1970年第一时刻的纪元参考 (1970-01-01T00:00)以来的计数,则解析为Instant

The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction). Instant类表示UTC时间轴上的一个时刻,分辨率为纳秒 (最多九(9)位小数)。

Instant instant = Instant.ofEpochMilli( myCountOfMilliseconds ) ;

To move from UTC to another time zone, apply a ZoneId to get a ZonedDateTime . 要从UTC移动到另一个时区,请应用ZoneId以获取ZonedDateTime

Specify a proper time zone name in the format of continent/region , such as America/Montreal , Africa/Casablanca , or Pacific/Auckland . continent/region的格式指定适当的时区名称 ,例如America/MontrealAfrica/CasablancaPacific/Auckland Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!). 切勿使用3-4字母缩写,例如ESTIST因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

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

Objects vs text 对象与文本

After assigning the time zone, then generate a string in your desired format (not before). 分配时区后, 然后生成所需格式的字符串(而不是之前)。 You may be conflating date-time values (objects) with strings representing their value textually. 您可能会将日期时间值(对象)与表示文本值的字符串混淆。 Learn to think of smart objects, not dumb strings. 学会思考智能对象,而不是愚蠢的字符串。

DateTimeFormatter

To generate a String in a particular format, use a DateTimeFormatter . 要以特定格式生成String,请使用DateTimeFormatter Search Stack Overflow as this been covered many many times, as have the other concepts shown here. 搜索Stack Overflow已被多次覆盖,这里显示的其他概念也是如此。 Of special note are the DateTimeFormatter.ofLocalized… methods. 特别值得注意的是DateTimeFormatter.ofLocalized…方法。


About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat . 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial . 要了解更多信息,请参阅Oracle教程 And search Stack Overflow for many examples and explanations. 并搜索Stack Overflow以获取许多示例和解释。 Specification is JSR 310 . 规范是JSR 310

Where to obtain the java.time classes? 从哪里获取java.time类?

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目是未来可能添加到java.time的试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more . 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

I was doing a similar thing in my previous project.You can use setTimeZone method of SimpleDateFormat class. 我在之前的项目中做了类似的事情。你可以使用SimpleDateFormat类的setTimeZone方法。 Something like this : 像这样的东西:

mydate.setTimeZone(TimeZone.getTimeZone("GMT -0400"));
    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);

This prints 这打印

Wed, Apr 3, '19

The other example offset you gave, +2:00 , is slightly more difficult since ZoneOffset.of requires either only hours ( +2 ) or two-digit hours before the colon ( +02:00 ). 您给出的另一个示例偏移量+2:00稍微困难一些,因为ZoneOffset.of只需要小时( +2 )或冒号前两位数小时( +02:00 )。 One solution is to fix the string before handing it to ZoneOffset : 一种解决方案是在将字符串交给ZoneOffset之前修复它:

    String utcOffsetString = "+2:00";
    utcOffsetString = utcOffsetString.replaceFirst("([-+])(\\d:\\d{2})", "$10$2");
    ZoneOffset offset = ZoneOffset.of(utcOffsetString);

The result is still Wed, Apr 3, '19 . 结果仍然是Wed, Apr 3, '19 If there were already 2-digit hours in the string, replaceFirst won't replace anything, so you just get the same string back. 如果字符串中已有2位数小时,则replaceFirst将不会替换任何内容,因此您只需返回相同的字符串即可。

If I change the offset to +08:00 , I get Thu, Apr 4, '19 instead. 如果我将偏移量更改为+08:00 ,那么我将改变Thu, Apr 4, '19

Edit: I frankly find the regular expression I use for fixing the offset string quite unreadable. 编辑:我坦率地发现我用来修复偏移字符串的正则表达式非常难以理解。 Here's a simpler way of fixing it: 这是一种更简单的修复方法:

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

Like Basil Bourque I am using java.time . 像Basil Bourque我正在使用java.time See all the details in his answer . 查看他答案中的所有细节。

Not exactly what your looking for but close 不完全是你想要的,但接近

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

If you keep the localization strings instead of the offsets this will work. 如果您保留本地化字符串而不是偏移量,这将起作用。 Or you can make a map. 或者你可以制作地图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM