我正在尝试将UTC字符串转换为小时和分钟。我从API获取了UTC字符串,但下面给出了一个示例。
当它到达@property
时,它会抛出一个Unparseable Date错误并引用字符串someDate
。
谁能看到我在这里做错了什么?
我如何从UTC获取日期的示例
setString
尝试将其转换为HH:mm
String utcStr = "1521698232";
Date setSunrise = new Date(Long.parseLong(sunrise)*1000);
答案 0 :(得分:1)
你工作太辛苦了,以迂回的方式行事。此外,您正在使用麻烦的旧过时类。另外,我怀疑你忽略了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。
" Thu Mar 22 05:57:06 GMT + 00:00 2018&#34 ;;
这是日期时间值的可怕格式。
在将日期时间值作为文本交换时,使用标准ISO 8601字符串。解析/生成字符串时, java.time 类默认使用ISO 8601格式。
Date
和SimpleDateFormat
类是麻烦的旧日期时间类的一部分,这些类现在是遗留的,取而代之的是 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/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用诸如EST
或IST
之类的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 Overflow为DateTimeFormatter
。你会发现很多讨论和例子。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance 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的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 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);