-1

我正在从 MSSQL 服务器数据库获取日期时间默认 CURRENT_TIMESTAMP结果,现在我需要解析这个日期、时间等。数据库结果就像2016-05-14 12:54:01.363

我只需要遍历这种日期时间格式。正如我在下面做的那样。

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     try
    {
        Date date = format.parse(dateStr);
        SimpleDateFormat todayFormat = new SimpleDateFormat("dd");
        String dateToday = todayFormat.format(date);
        format = dateToday.equals(today) ? new SimpleDateFormat("hh:mm a") : new SimpleDateFormat("dd LLL, hh:mm a");
        String date1 = format.format(date);
        timestamp = date1.toString();
        //
    }
    catch (ParseException e)
    {
        e.printStackTrace();
    }

但我收到以下错误:

    java.text.ParseException: Unparseable date: "{"date":"2016-05-14 12:54:01.363000","timezone":"UTC","timezone_type":3}" (at offset 0)

在第 3 行.ie Date date = format.parse(dateStr);

需要帮忙!

4

2 回答 2

2

问题取决于您如何构造格式变量,最好使用传入模式而不是默认模式。在您的情况下(参数类似于“2016-05-14 12:54:01.363”,那么格式可能是这样的:

DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date date = format.parse(dateStr);

如果您的 dataStr 是由 json Web 服务调用返回的,格式如异常中所示,那么您可以将 dateStr 映射到响应类型,例如假设它被称为 MyDate 类。

ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
MyDate myDate = mapper.readValue(dateStr, MyDate.class);
Date date = myDate.getDate();

如果您不知道返回类型,您可以简单地将其映射到 Map 类:

Map dateMap = new ObjectMapper().readValue(dateStr, Map.class);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date date = format.parse(dateMap.get("date"));
于 2016-05-14T22:02:03.470 回答
2

微秒

您的问题文本引用输入字符串 as2016-05-14 12:54:01.363但您的错误消息另有说明,2016-05-14 12:54:01.363000. 那些额外的三位数字是微秒

诸如 java.util.Date 之类的旧日期时间类仅解析为毫秒(小数点后 3 位表示秒的分数)。所以SimpleDateFormat不能处理这样的输入。截断输入字符串,或者更好地使用现代日期时间类。

java.time

更大的问题是您使用的是 Java 最早版本中过时的旧日期时间类。这些类已被Java 8 及更高版本中内置的java.time框架所取代。ThreeTen- Backport项目已将大部分 java.time 功能向后移植到 Java 6 和 7,并由ThreeTenABP进一步适应 Android 。因此,没有理由与那些陈旧且臭名昭著的麻烦课程搏斗。

java.time 类具有更精细的粒度,可解析为纳秒(秒的 9 位小数)。

在 java.time 中,Instant该类是 UTC 时间线上的一个时刻,分辨率为纳秒。AnInstant等效于java.util.Date具有更精细分辨率的除外。

有关在旧类型和 java.time 类型之间进行转换的更多信息,请参阅我对另一个问题的带图表的回答。

检索日期时间值作为日期时间类型

您应该从数据库中检索日期时间值作为日期时间类型,而不是字符串。如果您的 JDBC 驱动程序符合 JDBC 4.2(对JSR 221的更新,并在此处描述),您可以直接检索到OffsetDateTime. 您可以将 anOffsetDateTime视为与 UTCInstant偏移(数字小时、分钟和秒)。

java.time.OffsetDateTime odt = resultSet.getObject( 1 );

如果没有,请回退到使用旧的java.sql类型。对于日期时间,这意味着java.sql.Timestamp.

java.sql.Timestamp ts = resultSet.getTimestamp( 1 );

尽量减少对旧 java.sql 类型的使用,因为它们是 java.util.Date/.Calendar 等混乱的一部分。立即转换为 java.time。要进行转换,请查找添加到旧类的新方法,例如toInstant.

Instant instant = ts.toInstant();

解析

如果您必须解析该输入字符串,最简单的方法是使其符合ISO 8601标准格式。java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。

为了遵守,将中间的空格替换为T. 并且,假设这个字符串确实代表 UTC 中的一个时刻,附加一个Z. The是UTC的Z缩写。Zulu

String input = "2016-05-14 12:54:01.363000";
String inputModified = input.replace( " " , "T" );
Instant instant = Instant.parse( inputModified );

时区

该问题忽略了时区的关键问题。

最佳实践是以 UTC 格式存储日期时间值。更好的数据库会将传入的数据调整为 UTC。当作为 a 检索时,java.sql.Timestamp您的值是 UTC,转换为Instant.

日期和时间取决于时区。将时区 ( ZoneId) 应用于您InstantZonedDateTime.

ZoneId zoneId = zoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

然后询问以获得您需要的月份日期和时间。

int dayOfMonth = zdt.getDayOfMonth();

如果您希望将时间作为自己的对象,请使用LocalTime该类。

LocalTime localTime = zdt.toLocalTime();

如果您真的想要时间字符串,请使用java.time.format包。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "hh:mm a" );
String output = zdt.format( formatter );

更好的是,让 java.time 完成自动格式化的工作。请注意语言环境的使用,它决定了 (a) 人类语言的月份名称等,以及 (b) 文化规范,例如年-月-日等元素的顺序。显式指定区域设置比隐式依赖 JVM 的当前默认区域设置更好,后者可以在运行时更改。

DateTimeFormatter timeOfDayFormatter = DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT );
timeOfDayFormatter = timeOfDayFormatter.withLocale( Locale.CANADA_FRENCH );
String output = zdt.toLocalTime().format( timeOfDayFormatter );
于 2016-05-16T19:16:07.283 回答