在日期选取器上显示相同的日期,忽略设备的时区



>我正在显示一个日期。日期因设备更改的时区而异。例如 - 1960 年 1 月 1 日时区 GMT +5.30 转换为 1959 年 12 月 31 日时区 GMT -5.00。我的要求是日期应与任何时区相同。我已将日期转换为 UTC 日期,但日期仍然根据时区更改。我尝试了如下代码-

//Convering given date to UTC date using SimpleDateFormat
try {
final DateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
final Date date = sdf.parse(givenDate + "");
datePicker.setDate(date);
} catch (ParseException exception) {
exception.printStackTrace();
}

// Converting given date into GMT date using Timezone defference
final TimeZone tzLocal = TimeZone.getDefault();
final long gmtMillis = givenDate.getTime() - (tzLocal.getRawOffset());
final Date date = new Date();
date.setTime(gmtMillis);
datePicker.setDate(date);

我正在使用具有setDate(date)方法(不是android.widget.DatePicker)的自定义DatePicker

我已经检查了许多类似的问答,但没有运气。谢谢

不可能使用 java.util.Date

有了java.util.Date你不能。尽管类名,Date并不表示日期。这是一个时间点。因此,当 JVM 的默认时区自创建Date以来可能已更改时,无法检测创建Date时使用了哪个时区。当然,您可以尝试所有可能的时区。这通常会给你两个,偶尔三个可能的日期。因为它在所有时区中都不是相同的日期。

它可能并不像听起来那么糟糕,因为Date类设计不佳且早已过时,因此无论如何您都不应该再使用它。

解决方案:java.time 和 ThreeTenABP

java.time 是现代 Java 日期和时间 API,它提供了LocalDate类。LocalDate是没有一天中时间和时区的日期。因此,当您创建价值为 1960 年 1 月 1 日的LocalDate时,它将始终明确地为 1960 年 1 月 1 日。

LocalDate date = LocalDate.of(1960, Month.JANUARY, 1);
System.out.println(date);

输出没有什么神秘的:

1960年01月01日

因此,第一个建议是将您的自定义DatePicker类基于LocalDate而不是Date

如果您现在负担不起进行该更改的费用,短期解决方案是在调用setDate之前进行转换(因此仅在默认时区的最后一次更改发生之后):

Instant startOfDayInDefaultZone = date.atStartOfDay(ZoneId.systemDefault())
.toInstant();
Date oldFashionedDate = DateTimeUtils.toDate(startOfDayInDefaultZone);
System.out.println(oldFashionedDate);

我所在时区的输出是:

1960年1月01日星期五 00:00:00 CET

问:我可以在 Android 上使用 java.time 吗?

是的,java.time在较旧和较新的Android设备上运行良好。它只需要至少Java6

  • 在 Java 8 及更高版本以及较新的 Android 设备(从 API 级别 26)中,内置了现代 API。
  • 在Java 6和7中获取ThreeTen Backport,现代类的反向移植(JSR 310的ThreeTen;请参阅底部的链接)。
  • 在(较旧的)Android上使用Android版本的ThreeTen Backport。它被称为ThreeTenABP。并确保从带有子包的org.threeten.bp导入日期和时间类。

在上面的代码中,我使用来自反向端口的DateTimeUtilsInstant转换为Date。如果您的Android版本内置了java.time,请改用Date.from(startOfDayInDefaultZone)进行此转换。

链接

  • 所有关于java.util.Date
  • Oracle 教程:日期时间解释如何使用 java.time。
  • Java 规范请求 (JSR) 310,其中首次描述了java.time
  • ThreeTen Backport 项目,将java.time向 Java 6 和 7 的反向移植(JSR-310 为 ThreeTen)。
  • ThreeTenABP,ThreeTen Backport 的安卓版
  • 问:如何在Android项目中使用ThreeTenABP,并进行了非常详尽的解释。

相关内容

  • 没有找到相关文章

最新更新