将日期转换为SimpleDateFormat时抛出Unparseable Date错误

时间:2018-03-22 19:51:29

标签: java android date android-date

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

当它到达@property时,它会抛出一个Unparseable Date错误并引用字符串someDate

谁能看到我在这里做错了什么?

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

setString

尝试将其转换为HH:mm

String utcStr = "1521698232";
Date setSunrise = new Date(Long.parseLong(sunrise)*1000);

2 个答案:

答案 0 :(得分:1)

TL;博士

你工作太辛苦了,以迂回的方式行事。此外,您正在使用麻烦的旧过时类。另外,我怀疑你忽略了time zone的关键问题。

考虑到时区,这是一个更简单,更清洁的现代解决方案。

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年第一时间epoch reference UTC,1970-01-01T00:00Z以来,您的输入似乎代表了整整几秒钟。这有时称为Unix Time or POSIX Time

ISO 8601

  

" Thu Mar 22 05:57:06 GMT + 00:00 2018&#34 ;;

这是日期时间值的可怕格式。

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

避免遗留日期时间类

DateSimpleDateFormat类是麻烦的旧日期时间类的一部分,这些类现在是遗留的,取而代之的是 java.time 类。

Date已被Instant取代。 Instant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

String input = "1521698232" ;  // Count of seconds since epoch reference of 1970-01-01T00:00Z.
long secondsSinceEpoch = Long.parseLong( input ) ;
Instant instant = Instant.ofEpochSecond( secondsSinceEpoch ) ;
  

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

如上所述,Instant(如Date)位于UTC。如果您要求时间,您将获得UTC的时间。更有可能的是,你真的希望那个时刻的时间是某个地区(时区)人们使用的挂钟时间。

时区对于确定日期和时间至关重要。在任何特定时刻,日期和时间在全球范围内因地区而异。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4个字母伪区域,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;

应用该区域以从UTC进行调整,生成ZonedDateTime对象。

ZonedDateTime zdt = instant.atZone( z ) ;
  

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

现在要求时间。生成的LocalTime对象缺少日期并且缺少时区。这只是一个24小时制的时间。

LocalTime lt = zdt.toLocalTime() ;

如果您只关心小时和分钟,请关闭truncating以及秒和小数秒。通过ChronoUnit类指定截断级别。

LocalTime ltTrunc = lt.truncatedTo( ChronoUnit.MINUTES ) ;

以标准ISO 8601格式生成字符串。

String output = ltTrunc.toString() ;  // Generate a `String` in standard ISO 8601 format.
  

18时57

要生成其他格式的字符串,search Stack OverflowDateTimeFormatter。你会发现很多讨论和例子。

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

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

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 1 :(得分:1)

+00:00部分是UTC offset,您不能将其视为文字(内部引号,就像您所做的那样)。这是一个重要的信息,因为它告诉你日期所指的UTC前面或后面几个小时(在这种情况下,它是零,所以它与UTC本身相同)。

另一个细节是星期和月份名称是英文,因此您应该在班级中设置java.util.Locale。如果您不使用区域设置,它将使用JVM默认值,并且无法保证在所有环境中它始终为英语。如果您确定输入中使用的语言,请设置语言环境:

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);

对于输出,有两件事:

  • 使用hh将打印上午小时,这意味着从1到12的值。如果您希望小时值从0到23,请使用HH - 这都是解释in the docs
  • 小时的值将转换为设备的默认时区,这意味着并不总是与输入相同(在我的情况下,我的国家/地区正在使用-03:00 - 比UTC晚3个小时 - 所以小时的价值是凌晨2点。

要在输入中使用相同的偏移量,必须在格式化程序中设置它:

SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
String printDate = formatter.format(someDate); // 05:57

要使用java时间类,Basil的另一个答案会告诉您如何在Android中使用此API。我只想添加类似的代码来解析您的特定输入:

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);