Java 将日期转换为SimpleDataFormat时引发不可解析的日期错误

Java 将日期转换为SimpleDataFormat时引发不可解析的日期错误,java,android,date,android-date,Java,Android,Date,Android Date,我正在尝试将UTC字符串转换为小时和分钟。我从API中获取UTC字符串,但下面给出了一个示例 当它到达someDate时,它抛出一个不可解析的日期错误并引用字符串setString 有人能看出我做错了什么吗 我如何从UTC获取日期的示例 String utcStr = "1521698232"; Date setSunrise = new Date(Long.parseLong(sunrise)*1000); 正在尝试将其转换为HH:mm String setString = "Thu Mar

我正在尝试将UTC字符串转换为小时和分钟。我从API中获取UTC字符串,但下面给出了一个示例

当它到达
someDate
时,它抛出一个不可解析的日期错误并引用字符串
setString

有人能看出我做错了什么吗

我如何从UTC获取日期的示例

String utcStr = "1521698232";
Date setSunrise = new Date(Long.parseLong(sunrise)*1000);
正在尝试将其转换为HH:mm

String setString = "Thu Mar 22 05:57:06 GMT+00:00 2018";

Date someDate = new SimpleDateFormat("EEE MMM d HH:mm:ss z'+00:00' yyyy").parse(setString);

Date printDate = new SimpleDateFormat("hh:mm").format(someDate);
tl;博士 你工作太辛苦了,迂回而行。此外,您使用的是麻烦的过时类。此外,我怀疑你忽视了关键的问题

这是一个更简单、更干净的现代解决方案,考虑了时区

Instant.ofEpochSecond(                 // Represent a moment in time in UTC, with a resolution of nanoseconds.
    Long.parseLong( "1521698232" )     // Count of whole seconds since epoch of 1970-01-01T00:00:Z.
)                                      // Returns a `Instant` object.
.atZone(                               // Apply a time zone (`ZoneId`) to adjust from UTC to the wall-clock time of the target audience. 
    ZoneId.of( "Asia/Kolkata" )        // Use only proper time zone names `continent/region`. Never use 3-4 letter codes such as `IST` or `EST`. 
)                                      // Produces a `ZonedDateTime` object.
.toLocalTime()                         // Extract only the time-of-day as a `LocalTime` object.
.truncatedTo( ChronoUnit.MINUTES )     // Lop off any seconds and fractional second.
.toString()                            // Generate a String in standard ISO 8601 format: HH:MM:SS.SSSSSSSSS
11:27

纪元 转换UTC字符串

没有“UTC字符串”这样的东西

您的输入似乎表示自1970年、1970-01-01T00:00Z的第一刻起的整秒数。这有时被称为

ISO 8601 “2018年3月22日星期四05:57:06 GMT+00:00”

对于日期时间值来说,这是一种糟糕的格式

在将日期时间值交换为文本时,请使用标准字符串。默认情况下,java.time类在解析/生成字符串时使用格式

避免遗留日期时间类
Date
SimpleDateFormat
类是麻烦的旧日期时间类的一部分,这些类现在是遗留的,被java.time类取代

日期
替换为
即时
。该类表示时间线上的一个时刻,分辨率为(小数点的九(9)位)

instant.toString():2018-03-22T05:57:12Z

如上所述,
即时
(如
日期
)处于活动状态。如果您询问一天的时间,您将得到UTC的一天时间。更可能的情况是,你真的希望一天中某个时刻的时间是某个地区(时区)人们使用的挂钟时间

时区对于确定一天中的日期和时间至关重要。对于任何给定的时刻,一天中的日期和时间在全球各地因区域而异

大陆/地区
的格式指定,例如,或
太平洋/奥克兰
。切勿使用3-4个字母的伪时区,如
EST
IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)

应用该分区从UTC进行调整,生成一个对象

zdt.toString():2018-03-22T18:57:12+13:00[太平洋/奥克兰]

现在问一下一天的时间。结果对象缺少日期和时区。这只是一天中24小时时钟上的一个时间

LocalTime lt = zdt.toLocalTime() ;
如果你只关心小时和分钟,那就删掉秒和分秒。通过类指定截断级别

生成标准格式的字符串

18:57

以其他格式生成字符串,例如。你会发现许多讨论和例子


关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
java.sql.*

从哪里获得java.time类

  • ,及以后
    • 内置的
    • 标准JavaAPI的一部分,带有捆绑实现
    • Java9添加了一些次要功能和修复
    • 大部分java.time功能都在中向后移植到Java6和Java7
    • 更高版本的Android捆绑包实现了java.time类
    • 对于早期的Android(tl;dr 你工作太努力了,走得太迂回了。而且,你使用的是麻烦的陈旧过时的类。而且,我怀疑你忽视了这个关键问题

      这是一个更简单、更干净的现代解决方案,考虑了时区

      Instant.ofEpochSecond(                 // Represent a moment in time in UTC, with a resolution of nanoseconds.
          Long.parseLong( "1521698232" )     // Count of whole seconds since epoch of 1970-01-01T00:00:Z.
      )                                      // Returns a `Instant` object.
      .atZone(                               // Apply a time zone (`ZoneId`) to adjust from UTC to the wall-clock time of the target audience. 
          ZoneId.of( "Asia/Kolkata" )        // Use only proper time zone names `continent/region`. Never use 3-4 letter codes such as `IST` or `EST`. 
      )                                      // Produces a `ZonedDateTime` object.
      .toLocalTime()                         // Extract only the time-of-day as a `LocalTime` object.
      .truncatedTo( ChronoUnit.MINUTES )     // Lop off any seconds and fractional second.
      .toString()                            // Generate a String in standard ISO 8601 format: HH:MM:SS.SSSSSSSSS
      
      11:27

      纪元 转换UTC字符串

      没有“UTC字符串”这样的东西

      您的输入似乎代表了自1970年第一刻起的整秒数,1970-01-01T00:00Z。这有时被称为

      ISO 8601 “2018年3月22日星期四05:57:06 GMT+00:00”

      对于日期时间值来说,这是一种糟糕的格式

      在将日期时间值交换为文本时使用标准字符串。java.time类在解析/生成字符串时默认使用格式

      避免遗留日期时间类
      Date
      SimpleDateFormat
      类是麻烦的旧日期时间类的一部分,这些类现在是遗留的,被java.time类取代

      Date
      替换为
      Instant
      。该类表示时间线上的一个时刻,分辨率为(小数点的九(9)位)

      instant.toString():2018-03-22T05:57:12Z

      如上所述,
      即时
      (如
      日期
      )在中。如果您询问一天的时间,您将得到UTC的一天时间。更可能的情况是,您真正想要的是某个地区(时区)的人使用的挂钟时间

      时区对于确定一天中的日期和时间至关重要。对于任何给定的时刻,一天中的日期和时间在全球各地因区域而异

      请以
      大陆/地区
      的格式指定一个时区,例如,或
      太平洋/奥克兰
      。切勿使用3-4个字母的伪时区,例如
      EST
      IST
      ,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)

      将该区域应用于
      ZonedDateTime zdt = instant.atZone( z ) ;
      
      LocalTime lt = zdt.toLocalTime() ;
      
      LocalTime ltTrunc = lt.truncatedTo( ChronoUnit.MINUTES ) ;
      
      String output = ltTrunc.toString() ;  // Generate a `String` in standard ISO 8601 format.
      
      String setString = "Thu Mar 22 05:57:06 GMT+00:00 2018";
      SimpleDateFormat parser = new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy", Locale.ENGLISH);
      Date someDate = parser.parse(setString);
      
      SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
      formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
      String printDate = formatter.format(someDate); // 05:57
      
      String setString = "Thu Mar 22 05:57:06 GMT+00:00 2018";
      DateTimeFormatter parser = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss O yyyy", Locale.ENGLISH);
      OffsetDateTime odt = OffsetDateTime.parse(setString, parser);
      
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
      String printDate = formatter.format(odt);