将当前时间转换为 PST 并与另一个日期进行比较

Convert current time to PST and compare with another date

在我的一个模块中,我必须实现以下目标。

我正在从服务器获取 yyyy-MM-dd'T'HH:mm:ss'Z' 格式的日期。我必须在 PST 中转换此日期和当前日期,然后在 hours/mins/seconds.

中显示这两者之间的差异

为了将当前时间转换为太平洋标准时间,我编写了以下代码

        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 对象?

是否有任何其他方法以毫秒为单位获取两个日期(当前日期和曾经从服务器接收到的日期)之间的差异?

这里有很多问题,让我们看看:

所以首先你应该解析整个字符串,包括 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 - see how to use it in Android (或者只使用 java.time classes,如果您的 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

tl;博士

切勿使用 DateCalendarSimpleDateFormat classes.

而是使用 java.time classes.

ChronoUnit.MILLISECONDS.between( 
    Instant.parse( "2018-01-23T12:34:56Z" )  , 
    Instant.now() 
)

详情

是正确的。

Is there any other way to get difference between two dates (current and once received from server) in milliseconds?

是的,还有另一种方法,使用现代java.time classes.

ISO 8601

您输入的是标准 ISO 8601 格式。当 parsing/generating 字符串时,java.time classes 默认使用这些标准格式。因此无需指定格式模式。

最后的ZZulu的缩写,意思是UTC。不要像在示例代码中那样忽略它。

Instant

Instant class 表示 UTC 时间轴中的一个时刻,精度为纳秒。

String input = "2018-01-23T12:34:56Z" ;
Instant instant = Instant.parse( input ) ;

您尝试从 UTC 调整到 America/Los_Angeles 中的分区时间是不必要且无关紧要的。将时区应用于 UTC 值不会更改其在时间轴上的位置,只会更改 wall-clock 时间。因此,一对 UTC 之间经过的时间与应用时区后经过的时间相同。

经过的时间

要计算经过的时间,请使用 Duration

Duration d = Duration.between( instant , otherInstant ) ;

我建议使用 Duration 而不是单纯的毫秒数来跟踪经过的时间。但如果你坚持总毫秒数,使用ChronoUnit枚举。

long millisElapsed = ChronoUnit.MILLISECONDS.between( instant , otherInstant ) ;

切勿使用令人困惑的 poorly-designed 旧版 class,例如 DateCalendarSimpleDateFormat。只使用它们的替代品,java.time classes,因为它们更干净、更简单,并且 well-designed.