在我的一个模块中,我必须实现以下目标。
我在 yyyy-MM-dd' HH:mm:ss' Z' 格式中从服务器获取日期。我必须在PST中转换这个日期和当前日期,然后以小时/分钟/秒显示这两者之间的差异。
为了将当前时间转换为PST,我编写了以下代码
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"));
Date currentLocalTime = cal.getTime();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", LocaleManager.getLocale());
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
format.setTimeZone(tz);
String localTime = format.format(currentLocalTime);
Date currentDate = format.parse(localTime);
这里当前时间被转换为字符串(代码中的 localTime ),但是当我解析此字符串以获取Date对象时,我只在时区中获取日期。
我的问题是格式化程序是否在不同时区格式化日期然后解析为什么同一日期没有转换为Date对象?
有没有其他方法可以在两个日期(当前和从服务器收到一次)之间获得差异,以毫秒为单位?
答案 0 :(得分:2)
这里有很多问题,让我们看看:
Z
means that the date/time is in UTC。当您创建SimpleDateFormat
并将Z
放在引号('Z'
)中时,您将其视为文字(字母Z本身),所以不要这样做java.util.Date
班级没有有时区。 When you print it, it uses the JVM default timezone,但班级本身没有一个首先,您应该解析整个字符串,包括UTC信息。然后你使用另一个格式化程序将其转换为另一个时区:
// parse the date/time with Z
SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Date date = parser.parse("2018-03-21T10:00:00Z");
// convert to another timezone
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
format.setTimeZone(tz);
String formattedDate = format.format(date); // 2018-03-21T03:00:00-07:00
但我建议你使用threeten backport - 看看如何在Android here中使用它(或者只使用 java.time 类,如果你的API水平有它)。
此API更好更容易:
// parse input
Instant instant = Instant.parse("2018-03-21T10:00:00Z");
// convert to timezone
ZonedDateTime zdt = instant.atZone(ZoneId.of("America/Los_Angeles"));
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
System.out.println(zdt.format(fmt)); // 2018-03-21T03:00:00-07:00
答案 1 :(得分:1)
切勿使用Date
,Calendar
或SimpleDateFormat
类。
相反,请使用 java.time 类。
ChronoUnit.MILLISECONDS.between(
Instant.parse( "2018-01-23T12:34:56Z" ) ,
Instant.now()
)
Answer by QPS是正确的。
有没有其他方法可以在两个日期(当前和从服务器收到一次)之间获得差异,以毫秒为单位?
是的,还有另一种方法,使用现代的 java.time 类。
您的输入采用标准ISO 8601格式。在解析/生成字符串时, java.time 类默认使用这些标准格式。因此无需指定格式化模式。
最后Z
是Zulu
的缩写,表示UTC。不要像在你的示例代码中那样忽略这一点。
Instant
Instant
类表示UTC时间轴中的一个时刻,分辨率为纳秒。
String input = "2018-01-23T12:34:56Z" ;
Instant instant = Instant.parse( input ) ;
您在America/Los_Angeles
中尝试从UTC调整到分区时间是不必要的,也无关紧要。将时区应用于UTC值不会更改其在时间轴上的位置,只会更改挂钟时间。因此,一对UTC之间的经过时间与应用时区之后经过的时间相同。
要计算已用时间,请使用Duration
。
Duration d = Duration.between( instant , otherInstant ) ;
我建议使用Duration
而不是仅仅数毫秒来跟踪已用时间。但如果您坚持总毫秒数,请使用ChronoUnit
枚举。
long millisElapsed = ChronoUnit.MILLISECONDS.between( instant , otherInstant ) ;
永远不要使用设计不当的遗留类,例如Date
,Calendar
和SimpleDateFormat
。只使用他们的替换 java.time 类,因为它们更干净,更简单,并且设计得很好。