java.text.ParseException:无法解析的日期:“09:07:31 AM PDT”
java.text.ParseException: Unparseable date: "09:07:31 AM PDT"
我在响应中有一个字段,我想在添加几分钟之前对其进行解析。我写了以下导致错误的代码。
SimpleDateFormat df = new SimpleDateFormat("HH:MM:ss a SSS");
Date date = df.parse(currentTime);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.MINUTE, 10);
此处,当前时间为“09:07:31 AM PDT”
您需要在格式中使用正确的字母组合,此处:
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss aa zzz");
您可能还想查看 API 文档 [1]。
注意:如果您使用上述格式,解析将有效,但您还需要日期部分才能准确计算。这是一个示例,您的机器当前时区的当前日期用作日期部分。
String recievedTime = "09:07:31 AM PDT";
String currentDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss aa zzz");
Date date = df.parse(currentDate +" " + recievedTime);
[1] https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
tl;博士
LocalTime // Represent a time-of-day without a date and without a time zone or offset-from-UTC.
.parse(
"09:07:31 AM PDT".substring( 0 , 11 ) , // Remove the senseless `PDT` from the input.
DateTimeFormatter.ofPattern( "hh:mm:ss a" ) // Define a formatting pattern to match our modified input string.
) // Returns a `LocalTime` object.
.toString() // Generates text in standard ISO 8601 format to represent the value of our `LocalTime` object.
09:07:31
避免 Date
& Calendar
您使用的 date-time classes 与 Java 的最早版本捆绑在一起。这些在几年前被 JSR 310 中定义的现代 java.time classes 所取代。
切勿使用 Date
、Calendar
、SimpleDateFormat
等。
Date
class不适合
java.util.Date
class 代表一个时刻,一个 time-of-day 的日期,如 UTC 所示。您的输入缺少日期。所以你的输入不能用这个 class.
来表示
Time-of-day 带区域没有意义
您输入的 time-of-day 是一个错误的时区。 PDT
可能代表“太平洋夏令时”,表示 Daylight Saving Time (DST) 是否生效。这不是真正的时区名称。相反,应使用时区名称,例如 America/Los_Angeles
。
无论如何,time-of-day 与时区的组合毫无意义。没有日期的上下文,时区就没有意义。
LocalTime
我建议您提取 time-of-day 并忽略 PDT
。取前11个字符。
String input = "09:07:31 AM PDT";
String s = input.substring( 0 , 11 ); // Uses annoying zero-based index counting. So asking for first through the eleventh characters requires ( 0 , 11 ).
定义格式模式以匹配我们修改后的输入字符串。
DateTimeFormatter f = DateTimeFormatter.ofPattern( "hh:mm:ss a" );
解析为 LocalTime
、没有日期和时区的 time-of-day 或 offset-from-UTC。
LocalTime lt = LocalTime.parse( s , f );
lt.toString(): 09:07:31
ZonedDateTime
为了好玩,让我们为您的 time-of-day 应用一个时区,并为 ZonedDateTime
应用一个日期。
LocalTime lt = LocalTime.parse( "01:59:00 AM PDT".substring( 0 , 11 ) , DateTimeFormatter.ofPattern( "hh:mm:ss a" ) );
LocalDate ld = LocalDate.of( 2020 , Month.MARCH , 7 );
ZoneId z = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
ZonedDateTime zdtLater = zdt.plusMinutes( 5 );
System.out.println( "zdtLater = " + zdtLater );
我们得到 2:04 上午。
zdtLater = 2020-03-07T02:04-08:00[America/Los_Angeles]
将该日期更改为 8 号。
LocalTime lt = LocalTime.parse( "01:59:00 AM PDT".substring( 0 , 11 ) , DateTimeFormatter.ofPattern( "hh:mm:ss a" ) );
LocalDate ld = LocalDate.of( 2020 , Month.MARCH , 8 );
ZoneId z = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
ZonedDateTime zdtLater = zdt.plusMinutes( 5 );
System.out.println( "zdtLater = " + zdtLater );
我们得到 3:04 上午,而不是 2:04 上午。
zdtLater = 2020-03-08T03:04-07:00[America/Los_Angeles]
日期是 time-of-day 在时区中的含义。
偏移量随时间变化。这就是时区的意义。 America/Los_Angeles
这样的时区是北美西海岸很多地区的人们使用的offset的过去、现在和未来变化的历史。 2020 年 3 月 7 日,偏移量比 UTC 晚八小时。 2020 年 3 月 8 日,偏移量更改为比 UTC 晚 7 小时。凌晨 2 点的第一刻,时钟跳了一个小时到凌晨 3 点。 8 日凌晨 2 点从未像 7 日那样出现。
OffsetTime
java.time 框架确实提供了 OffsetTime
class。这表示 time-of-day 和 offset-from-UTC.
这个 class 没有意义,原因与上面讨论的相同。带有偏移量但没有日期的 time-of-day 没有任何用处。我认为这被添加到 java.time 只是为了匹配 SQL-standard 类型 TIME WITH TIME ZONE
,同时 LocalTime
匹配 TIME WITHOUT TIME ZONE
.但是这个 TIME WITH TIME ZONE
类型在 SQL 中没有意义。这个问题是其他人注意到的,而不仅仅是我的意见。这不是 SQL 标准中唯一没有意义的事情。
此外,您的输入带有时区(或者至少时区是 PDT
的 mis-use 指定的),而不是偏移量。偏移量是 hour-minutes-seconds 的数字,仅此而已。如上所述,时区是偏移量变化的历史。
我在响应中有一个字段,我想在添加几分钟之前对其进行解析。我写了以下导致错误的代码。
SimpleDateFormat df = new SimpleDateFormat("HH:MM:ss a SSS");
Date date = df.parse(currentTime);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.MINUTE, 10);
此处,当前时间为“09:07:31 AM PDT”
您需要在格式中使用正确的字母组合,此处:
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss aa zzz");
您可能还想查看 API 文档 [1]。
注意:如果您使用上述格式,解析将有效,但您还需要日期部分才能准确计算。这是一个示例,您的机器当前时区的当前日期用作日期部分。
String recievedTime = "09:07:31 AM PDT";
String currentDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss aa zzz");
Date date = df.parse(currentDate +" " + recievedTime);
[1] https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
tl;博士
LocalTime // Represent a time-of-day without a date and without a time zone or offset-from-UTC.
.parse(
"09:07:31 AM PDT".substring( 0 , 11 ) , // Remove the senseless `PDT` from the input.
DateTimeFormatter.ofPattern( "hh:mm:ss a" ) // Define a formatting pattern to match our modified input string.
) // Returns a `LocalTime` object.
.toString() // Generates text in standard ISO 8601 format to represent the value of our `LocalTime` object.
09:07:31
避免 Date
& Calendar
您使用的 date-time classes 与 Java 的最早版本捆绑在一起。这些在几年前被 JSR 310 中定义的现代 java.time classes 所取代。
切勿使用 Date
、Calendar
、SimpleDateFormat
等。
Date
class不适合
java.util.Date
class 代表一个时刻,一个 time-of-day 的日期,如 UTC 所示。您的输入缺少日期。所以你的输入不能用这个 class.
Time-of-day 带区域没有意义
您输入的 time-of-day 是一个错误的时区。 PDT
可能代表“太平洋夏令时”,表示 Daylight Saving Time (DST) 是否生效。这不是真正的时区名称。相反,应使用时区名称,例如 America/Los_Angeles
。
无论如何,time-of-day 与时区的组合毫无意义。没有日期的上下文,时区就没有意义。
LocalTime
我建议您提取 time-of-day 并忽略 PDT
。取前11个字符。
String input = "09:07:31 AM PDT";
String s = input.substring( 0 , 11 ); // Uses annoying zero-based index counting. So asking for first through the eleventh characters requires ( 0 , 11 ).
定义格式模式以匹配我们修改后的输入字符串。
DateTimeFormatter f = DateTimeFormatter.ofPattern( "hh:mm:ss a" );
解析为 LocalTime
、没有日期和时区的 time-of-day 或 offset-from-UTC。
LocalTime lt = LocalTime.parse( s , f );
lt.toString(): 09:07:31
ZonedDateTime
为了好玩,让我们为您的 time-of-day 应用一个时区,并为 ZonedDateTime
应用一个日期。
LocalTime lt = LocalTime.parse( "01:59:00 AM PDT".substring( 0 , 11 ) , DateTimeFormatter.ofPattern( "hh:mm:ss a" ) );
LocalDate ld = LocalDate.of( 2020 , Month.MARCH , 7 );
ZoneId z = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
ZonedDateTime zdtLater = zdt.plusMinutes( 5 );
System.out.println( "zdtLater = " + zdtLater );
我们得到 2:04 上午。
zdtLater = 2020-03-07T02:04-08:00[America/Los_Angeles]
将该日期更改为 8 号。
LocalTime lt = LocalTime.parse( "01:59:00 AM PDT".substring( 0 , 11 ) , DateTimeFormatter.ofPattern( "hh:mm:ss a" ) );
LocalDate ld = LocalDate.of( 2020 , Month.MARCH , 8 );
ZoneId z = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
ZonedDateTime zdtLater = zdt.plusMinutes( 5 );
System.out.println( "zdtLater = " + zdtLater );
我们得到 3:04 上午,而不是 2:04 上午。
zdtLater = 2020-03-08T03:04-07:00[America/Los_Angeles]
日期是 time-of-day 在时区中的含义。
偏移量随时间变化。这就是时区的意义。 America/Los_Angeles
这样的时区是北美西海岸很多地区的人们使用的offset的过去、现在和未来变化的历史。 2020 年 3 月 7 日,偏移量比 UTC 晚八小时。 2020 年 3 月 8 日,偏移量更改为比 UTC 晚 7 小时。凌晨 2 点的第一刻,时钟跳了一个小时到凌晨 3 点。 8 日凌晨 2 点从未像 7 日那样出现。
OffsetTime
java.time 框架确实提供了 OffsetTime
class。这表示 time-of-day 和 offset-from-UTC.
这个 class 没有意义,原因与上面讨论的相同。带有偏移量但没有日期的 time-of-day 没有任何用处。我认为这被添加到 java.time 只是为了匹配 SQL-standard 类型 TIME WITH TIME ZONE
,同时 LocalTime
匹配 TIME WITHOUT TIME ZONE
.但是这个 TIME WITH TIME ZONE
类型在 SQL 中没有意义。这个问题是其他人注意到的,而不仅仅是我的意见。这不是 SQL 标准中唯一没有意义的事情。
此外,您的输入带有时区(或者至少时区是 PDT
的 mis-use 指定的),而不是偏移量。偏移量是 hour-minutes-seconds 的数字,仅此而已。如上所述,时区是偏移量变化的历史。