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

时间:2014-09-19 16:35:03

标签: java javascript mongodb date jodatime

我正在尝试从/向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();
}

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

由于

3 个答案:

答案 0 :(得分:22)

如果您使用的是Java 7或更早版本,则可以参考此post

如果您使用的是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);

更新

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

  

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

可以使用一些具体的课程,例如LocalDateLocalDateTimeOffsetDateTimeZonedDateTime等。

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

答案 1 :(得分:6)

TL;博士

OffsetDateTime.parse( "2015-10-27T16:22:27.605-07:00" )
.toInstant()
.toString()
  

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

Instant

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

OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;
  

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

如果您在代码中使用此UTC值很多,并且通常应该是这样,那么您可能会发现使用Instant对象更加清晰。根据定义,Instant 总是在UTC中。我们可以从Instant中提取OffsetDateTime

Instant instant = odt.toInstant() ;
  

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

请注意,我们上面的所有三个对象(odtodtUtcinstant)都代表同一时刻,即时间轴上的相同点。唯一不同的是他们的挂钟时间。

ZonedDateTime

顺便说一句,如果您希望同一时刻调整到某个地区的人使用的挂钟时间,请通过ZoneId指定一个时区来获取ZonedDateTime对象

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
  

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

java.time

中使用具体类

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

在本课题的具体情况中,课程OffsetDateTime适合而不是TemporalAccessor


关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

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

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore


约达时间

更新: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();

如果可能,请避免使用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.

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

DateTime dateTimeMontréal = dateTimeUtc.withZone( DateTimeZone.forID( "America/Montreal" ) );

答案 2 :(得分:0)

Java8的本机解决方案

Date.from(ZonedDateTime.parse("1994-11-05T08:15:30+05:30").toInstant())

Date.from(ZonedDateTime.parse("1994-11-05T13:15:30Z").toInstant())