为什么我无法使用java.text.SimpleDateFormat的解析方法从PST中解析2013-03- 10 T02:59:59 Z?

lymnna71  于 2023-02-02  发布在  Java
关注(0)|答案(1)|浏览(167)

对于某些输入值,虽然格式和所有内容都是正确的,但我从SimpleDateFormat.parse(字符串输入)方法中得到了ParseException。
我正处于需要将时间从PST时区转换为本地时区的场景中;除了2013-03- 10 T02:00:00 Z到2013-03- 10 T02:59:59 Z,对于可接受的输入,几乎所有时间都工作,感觉很奇怪;我尝试了几个JDK和机器,但结果是一样的,它抛出

Method threw 'java.text.ParseException' exception.

我的期望是正确地解析这个日期并返回非空的日期对象,而不是抛出异常。
测试代码段:

public static void main(String[] args) throws Exception {
        System.out.println(getDateFromString("2013-03-10T02:59:59Z", "yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH));
    }

    public static Date getDateFromString(String dateText, String format, Locale locale) {
        Date date = null;
        SimpleDateFormat simpleDateFormat = null;
        try {
            simpleDateFormat = new SimpleDateFormat(format, locale);
            simpleDateFormat.setTimeZone(TimeZone.getTimeZone("PST"));
            //Supporting strict validation of date format
            simpleDateFormat.setLenient(false);
            date = simpleDateFormat.parse(dateText);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
rm5edbpk

rm5edbpk1#

TL;医生

分析尝试失败,因为您错误地解释了输入文本。产生的错误值表示特定时区中从未存在的日期和时间。
相反,使用 * java. time * 类正确地解析输入,并调整到时区。

Instant
.parse( "2013-03-10T02:00:00Z" )
.atZone( ZoneId.of( "America/Los_Angeles" ) )
.toString()

参见Ideone.com
2013年3月9日18:00 - 8:00 [美洲/洛杉矶]
你的密码
在日期-时间格式中,不要在Z的两边加上引号,这意味着要期待但忽略重要信息:相对于UTC的零时-分-秒的偏移量。
你问:
为什么我会遇到当前代码的问题?
正如其他人所评论的,我假设旧的日期-时间类试图解析您的xx输入,同时猜测值PST表示时区America/Los_Angeles。这可能是因为(a)您告诉格式化程序忽略由Z表示的实际预期偏移量零,然后您(b)告诉格式化程序假设默认时区PST。
因此,您的代码违背了向您发送输入数据的人的意图,您试图解析一个值2013 - 03 - 10 02:59:59(美国/洛杉矶),而不是UTC格式的2013 - 03 - 10 02:59:59。
正如其他人评论的那样,那一刻从未存在过. At 2 AM on March 13, 2013 all the people using time zone America/Los_Angeles jumped their clocks forward to 3 AM.这一跳是Daylight Saving Time (DST)的"Spring在前"切换,3月13日那天只有23小时长,而不是24小时,02:00 - 03:00被切除了。
👉🏽 因此,您的解析尝试失败了,因为您被误解的输入碰巧被发现是无意义的。

修订代码

使用现代的 * java.time * 类,不要使用那些糟糕的遗留类。
您的输入为标准ISO 8601格式。无需定义格式模式。

Instant instant = Instant.parse( "2013-03-10T02:59:059Z" ) ;

立即转换为字符串()= 2013年3月10日T02:59:59Z
调整到所需时区。
PST不是一个真正的时区。也许您指的是美国大陆西海岸大部分地区使用的时区。

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

zdt.到字符串()= 2013年3月9日18:59:59 - 08:00 [美洲/洛杉矶]
注意日期和时间的变化。
See that code run.
如果您必须使用java.util.Date来与尚未更新到 * java.time * 的代码进行互操作,请使用添加到旧类中的新转换方法。

java.util.Date d = Date.from( instant ) ;  // A date-time as seen in UTC, an offset of zero hours-minutes-seconds.

在发布之前一定要搜索栈溢出。所有这些在之前已经讨论过很多次了。搜索以了解更多。

相关问题