繁体   English   中英

yyyy-MM-dd'T'HH:mm:ss 和 yyyy-MM-dd'T'HH:mm:ssXXX 之间的日期格式差异

[英]Date formats difference between yyyy-MM-dd'T'HH:mm:ss and yyyy-MM-dd'T'HH:mm:ssXXX

我正在尝试使用这两种格式解析日期2014-12-03T10:05:59.5646+08:00

  • yyyy-MM-dd'T'HH:mm:ss
  • yyyy-MM-dd'T'HH:mm:ssXXX

当我使用yyyy-MM-dd'T'HH:mm:ss解析时,它工作正常,但是当我解析yyyy-MM-dd'T'HH:mm:ssXXX会抛出ParseException

解析日期的正确格式是什么,这两种格式之间究竟有什么区别?

注意:我不能使用 Joda :(

使用这种格式yyyy-MM-dd'T'HH:mm:ss.SSSSX

来自SimpleDateFormat API

//Letter    Date or Time Component  Presentation        Example
  S         Millisecond             Number              978
  X         Time zone               ISO 8601 time zone  -08; -0800; -08:00

用:

DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSX");
String date = "2014-12-03T10:05:59.5646+08:00";
System.out.println(format.parse(date));

输出:

Wed Dec 03 03:06:04 CET 2014

这些是有效的格式:

yyyy-MM-dd'T'HH:mm:ss.SSSZ       >>>  e.g.: 2001-07-04T12:08:56.235-0700

yyyy-MM-dd'T'HH:mm:ss.SSSXXX     >>>  e.g.: 2001-07-04T12:08:56.235-07:00

编辑:
顺便说一句,“X”指的是(ISO 8601 时区)

当我使用yyyy-MM-dd'T'HH:mm:ss解析时,它工作正常,但是当我解析yyyy-MM-dd'T'HH:mm:ssXXX会抛出ParseException

解析日期的正确格式是什么,这两种格式之间究竟有什么区别?

我们先来看看yyyy-MM-dd'T'HH:mm:ss

文档中检查以下行(强调我的):

从给定字符串的开头解析文本以生成日期。 该方法可能不会使用给定字符串的整个文本

所以,基本上,格式yyyy-MM-dd'T'HH:mm:ss只考虑到2014-12-03T10:05:59并忽略秒和时区偏移信息的分数。

yyyy-MM-dd'T'HH:mm:ssXXX什么问题?

在这种格式中,您正确放置了时区偏移的符号,但在几分之一秒内错过了符号。

使用SimpleDateFormat解析它的正确格式是什么?

简短的回答:没有

长答案: SimpleDateFormat无法正确处理超过毫秒的精度(即.之后的 3 位数字),因此没有任何格式可以正确解析它。 使其正确的唯一方法是将数字保留在. 最多三位数,例如2014-12-03T10:05:59.564+08:002014-12-03T10:05:59.56+08:00等。让我们看看SimpleDateFormat将如何解析2014-12-03T10:05:59.5646+08:00错了。

SimpleDateFormat考虑 之后的数字. 作为毫秒数(而不是现代日期时间 API 考虑的几分之一秒)。 因此,计算过程如下:

5646 milliseconds = 5 seconds + 646 milliseconds
2014-12-03T10:05:59 + 5 seconds + 646 milliseconds = 2014-12-03T10:06:04.646

让我们使用代码验证它:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) throws ParseException {
        String strDateTime = "2014-12-03T10:05:59.5646+08:00";
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
        Date date = sdf.parse(strDateTime);

        sdf.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
        System.out.println(sdf.format(date));
    }
}

输出:

2014-12-03T10:06:04.646+08:00

时间

随着 2014 年 3 月 Java SE 8 的发布,过时且容易出错的遗留 Date-Time API( java.util Date-Time 类型及其格式化类型SimpleDateFormat等)被java.time取代, 现代java.time 时间 API * . 强烈建议停止使用旧 API 并切换到这个新 API。

使用现代 API java.time解决方案:

import java.time.OffsetDateTime;

public class Main {
    public static void main(String[] args) {
        OffsetDateTime odt = OffsetDateTime.parse("2014-12-03T10:05:59.5646+08:00");
        System.out.println(odt);
    }
}

输出:

2014-12-03T10:05:59.564600+08:00

是不是很酷?

现代日期时间 API 基于ISO 8601 ,只要日期时间字符串符合 ISO 8601 标准,就不需要明确使用DateTimeFormatter对象。

顺便说一句,无论出于何种原因,如果您需要将OffsetDateTime这个对象转换为java.util.Date的对象,您可以这样做:

Date date = Date.from(odt.toInstant());

Trail: Date Time 中了解有关java.time更多信息, 现代 Date-Time API *


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目和您的 Android API 工作级别仍然不符合 Java-8,请检查 通过 desugaringHow to use ThreeTenABP in Android Project 可用的 Java 8+ APIs

我遇到了类似的问题,我无法直接在 Kotlin 中转换时间戳

所以我自己写了代码

首先通过创建一个数据类来存储

Data class TimeAndDate(
    val day : String,
    val month : String,
    val year : String,
    val hours : String,
    val minutes : String
)

现在用于转换字符串

 //for the type of yyyy-MM-dd'T'HH:mm:ss.SSS
// Here timeStamp is a String in the above format
        fun timeAndDateConverter(timeStamp: String): TimeAndDate {
            val day = timeStamp.subSequence(8, 10).toString()
            val year = timeStamp.subSequence(2, 4).toString()
            var month = timeStamp.subSequence(5, 7).toString()
            when (month) {
                "01" -> month = "Jan"
                "02" -> month = "Feb"
                "03" -> month = "Mar"
                "04" -> month = "Apr"
                "05" -> month = "May"
                "06" -> month = "Jun"
                "07" -> month = "Jul"
                "08" -> month = "Aug"
                "09" -> month = "Sep"
                "10" -> month = "Oct"
                "11" -> month = "Nov"
                "12" -> month = "Dec"

            }
            val hours = timeStamp.subSequence(11, 13).toString()
            val minutes = timeStamp.subSequence(14, 16).toString()

            return TimeAndDate(
                day = day,
                month = month,
                year = year,
                hours = hours,
                minutes = minutes
            )

        }

此函数将返回数据类,我们可以从中获取所有单个元素

暂无
暂无

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

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