使用UTC时区将ISO8601日期字符串解析为日期

Dim*_*iwa 13 javascript java date jodatime mongodb

我正在尝试从/向JavaScript应用程序序列化/反序列化日期.

服务器端,我用java,JodaTime安装就可以了.我发现了如何使用UTC时区序列化到ISO,但无法找到如何进行反向操作.

这是我的代码

public static String getIsoDate( Date date )
{
    SimpleDateFormat  dateToIsoDateString = new SimpleDateFormat( ISO_8601_DATE_FORMAT );
    TimeZone tz = TimeZone.getTimeZone("UTC");
    dateToIsoDateString.setTimeZone( tz );
    return dateToIsoDateString.format( date );
}

// this will return a date with GMT timezone
public static Date getDateFromIsoDateString( String iso8601date )
{
    DateTimeFormatter jodaParser = ISODateTimeFormat.dateTimeNoMillis();
    return jodaParser.parseDateTime( iso8601date ).toDate();
}
Run Code Online (Sandbox Code Playgroud)

我不介意使用或不使用Joda,只需要一个快速和有效的解决方案,

谢谢

alw*_*arn 23

如果您使用的是Java 7或更早版本,可以参考这篇文章.

如果您使用的是Java 8,则可以:

    DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;
    TemporalAccessor accessor = timeFormatter.parse("2015-10-27T16:22:27.605-07:00");

    Date date = Date.from(Instant.from(accessor));
    System.out.println(date);
Run Code Online (Sandbox Code Playgroud)

更新

正如@BasilBourque在评论中所指出的,TemporalAccessor是java框架级接口,不建议在应用程序代码中使用,建议使用具体的类而不是接口.

此接口是框架级接口,不应在应用程序代码中广泛使用.相反,应用程序应创建并传递具体类型的实例,例如LocalDate.造成这种情况的原因有很多,其中一部分原因是此接口的实现可能在ISO之外的日历系统中.请参阅ChronoLocalDate以更全面地讨论这些问题.

有一些具体的类可供使用,如LocalDate,LocalDateTime,OffsetDateTime,ZonedDateTime等.

DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;

OffsetDateTime offsetDateTime = OffsetDateTime.parse("2015-10-27T16:22:27.605-07:00", timeFormatter);

Date date = Date.from(Instant.from(offsetDateTime));
System.out.println(date);
Run Code Online (Sandbox Code Playgroud)


Bas*_*que 9

TL;博士

OffsetDateTime.parse( "2015-10-27T16:22:27.605-07:00" )
.toInstant()
.toString()
Run Code Online (Sandbox Code Playgroud)

2015-10-27T23:22:27.605Z

细节

您的问题不明确且具体.也许这些小例子会有所帮助.将旧的java.util.Date和.Calendar类与Joda-Time混合可能会使您感到困惑.Joda-Time完全取代了那些类而不是扩充.

java.time

现代java.time类取代了Java中的遗留日期时间类以及提供灵感的Joda-Time库.

OffsetDateTime

所述OffsetDateTime类表示在时间轴上的力矩与特定偏移从-UTC确定其挂钟时间.

在解析/生成字符串时,java.time类在默认情况下使用标准ISO 8601格式.因此无需指定格式化模式.

OffsetDateTime odt = OffsetDateTime.parse( "2015-10-27T16:22:27.605-07:00" ) ;
Run Code Online (Sandbox Code Playgroud)

Instant

要从UTC后面七个小时的偏移调整到UTC本身,我们需要在一天中添加七个小时并在需要时滚动日期.该OffsetDateTime班能为我们做这项工作.使用ZoneOffset.UTC常量指定UTC .

OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;
Run Code Online (Sandbox Code Playgroud)

odtUtc.toString():2015-10-27T23:22:27.605Z

如果您在代码中使用此UTC值很多,并且通常应该是这样,那么您可能会发现使用Instant对象更加清晰.一个Instant始终以UTC定义.我们可以提取InstantOffsetDateTime.

Instant instant = odt.toInstant() ;
Run Code Online (Sandbox Code Playgroud)

instant.toString():2015-10-27T23:22:27.605Z

注意,这三种我们的上述对象(odt,odtUtc,instant)都表示非常相同的同时时刻,在时间轴上的相同点.唯一不同的是他们的挂钟时间.

ZonedDateTime

顺便说一句,如果你想看到调整到使用的挂钟时间由某一区域的人们,同一时刻,通过指定一个时区ZoneId得到一个ZonedDateTime对象.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Run Code Online (Sandbox Code Playgroud)

zdt.toString():2015-10-27T19:22:27.605-04:00 [美国/蒙特利尔]

java.time中使用具体类

always_a_rookie_to_learn答案与上述方法类似,但使用的是界面TemporalAccessor.通常,使用更高的接口和超类是Java中的一个好主意.但不是在这里.该java.time文档解释自己的设计意图我们在应用程序使用较低的更具体的类.通常,抽象仅供框架内部使用.

在本课题的具体情况下,该课程OffsetDateTime是适当的而不是TemporalAccessor.


关于java.time

java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date,Calendar,和SimpleDateFormat.

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

要了解更多信息,请参阅Oracle教程.并搜索Stack Overflow以获取许多示例和解释.规范是JSR 310.

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

从哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval,YearWeek,YearQuarter,和更多.


乔达时间

更新:Joda-Time项目处于维护模式,它建议迁移到java.time类.此部分保留完整的历史记录.

对于字符串,Joda-Time默认为ISO 8601,包括解析和生成.Joda-Time内置了ISO 8601的默认解析器,因此只需将兼容字符串传递给构造函数或静态parse方法即可.

java.util.Date date = new DateTime( "2010-01-01T12:00:00+01:00Z" ).toDate();
Run Code Online (Sandbox Code Playgroud)

如果可能的话,避免使用java.util.Date和.Calendar,并坚持使用Joda-Time和它的类DateTime.仅在其他类需要的地方使用.Date.

DateTime dateTimeUtc = new DateTime( someJavaDotUtilDotDate, DateTimeZone.UTC ); // Joda-Time can convert from java.util.Date type which has no time zone.
String output = dateTime.toString(); // Defaults to ISO 8601 format.
DateTime dateTimeUtc2 = new DateTime( output, DateTimeZone.UTC ); // Joda-Time can parse ISO 8601 strings.
Run Code Online (Sandbox Code Playgroud)

对于演示,请调整到用户期望的时区.

DateTime dateTimeMontréal = dateTimeUtc.withZone( DateTimeZone.forID( "America/Montreal" ) );
Run Code Online (Sandbox Code Playgroud)