有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java解析ISO8601日期字符串到UTC时区的日期

我正在尝试从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) 个答案

  1. # 1 楼答案

    tl;博士

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

    2015-10-27T23:22:27.605Z

    细节

    你的问题不清楚也不具体。也许这些小例子会有所帮助。混合旧爪哇语。util。日期和日期。带乔达时间的日历课程可能会让你困惑。Joda Time完全取代了那些职业,而不是增加

    爪哇。时间

    现代的爪哇。时间类取代了Java中遗留的日期时间类以及提供了灵感的Joda时间库

    OffsetDateTime

    ^{}类表示时间线上的一个时刻,它与UTC的特定偏移量决定了它的挂钟时间

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

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

    Instant

    要将UTC后7小时的偏移量调整为UTC本身,我们需要在一天的时间上增加7小时,并根据需要滚动日期。{}类可以为我们完成这项工作。使用ZoneOffset.UTC常量指定UTC

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

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

    如果您在代码中经常使用这个UTC值,并且通常应该这样做,那么您可能会发现使用Instant对象更清晰。根据定义,UTC中的Instant始终。我们可以从OffsetDateTime中提取一个Instant

    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[America/Montreal]

    java中使用具体的类。时间

    {a3}与上述方法类似,但使用接口{a4}。一般来说,在Java中使用更高级的接口和超类是一个好主意。但不是在这里。java。时间文档解释说,他们的设计意图是让我们在应用程序中使用较低级别的更具体的类。这些抽象一般只在框架内供内部使用

    在这个问题的特定情况下,类OffsetDateTime是合适的,而不是TemporalAccessor


    关于java。时间

    java.time框架内置于Java8及更高版本中。这些类取代了麻烦的legacy日期时间类,如^{}^{}、&^{}

    目前位于maintenance modeJoda-Time项目建议迁移到java.time

    要了解更多信息,请参阅Oracle Tutorial。并在Stack Overflow中搜索许多示例和解释。规范是JSR 310

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

    在哪里可以获得java。时间课

    ThreeTen-Extra项目扩展了java。有额外课程的时间。这个项目是java未来可能增加的一个试验场。时间你可以在这里找到一些有用的类,比如^{}^{}^{}more


    乔达时间

    更新:Joda Time项目处于维护模式,建议迁移到java。上课时间。这一部分在历史上保持不变

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

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

    如果可能,避免使用java。util。日期和日期。日历,坚持使用Joda TimeDateTime等课程。使用仅在其他课程要求时注明日期

    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. # 2 楼答案

    如果您使用的是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框架级接口,不建议在应用程序代码中使用,建议使用具体类而不是接口

    This interface is a framework-level interface that should not be widely used in application code. Instead, applications should create and pass around instances of concrete types, such as LocalDate. There are many reasons for this, part of which is that implementations of this interface may be in calendar systems other than ISO. See ChronoLocalDate for a fuller discussion of the issues.

    有几个具体的类可以使用,比如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);
    
  3. # 3 楼答案

    Java8中的本机解决方案

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