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

Android 在日期选择器上显示相同的日期,忽略设备的时区,android,date,datepicker,timezone,utc,Android,Date,Datepicker,Timezone,Utc,我正在展示一个日期。日期随设备更改的时区而变化。例如,时区GMT+5.30的-1960年1月1日转换为时区GMT-5.00的1959年12月31日。我的要求是,日期应与任何时区相同。我已将日期转换为UTC日期,但日期仍随时区而变化。我尝试了以下几个代码- //Convering given date to UTC date using SimpleDateFormat try { final DateFormat sdf = new SimpleDateFormat("EEE M

我正在展示一个日期。日期随设备更改的时区而变化。例如,时区GMT+5.30的-1960年1月1日转换为时区GMT-5.00的1959年12月31日。我的要求是,日期应与任何时区相同。我已将日期转换为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();
    }

我使用的自定义日期选择器具有setDatedate方法,而不是android.widget.DatePicker

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

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

它可能没有听起来那么糟糕,因为Date类的设计很差,而且很早就过时了,所以无论如何你不应该再使用它了

解决方案:java.time和ThreeTenABP 现代java日期和时间API java.time提供了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月1日星期五00:00:00 CET

问题:我可以在Android上使用java.time吗? 是的,java.time在较旧和较新的Android设备上运行良好。它至少需要Java6

在Java8和更高版本以及API级别为26的较新Android设备上,内置了现代API。 在Java6和Java7中,获取ThreeTen Backport,即JSR310的现代类ThreeTen的Backport;请参阅底部的链接。 在较旧的Android上,使用Android版本的ThreeTen Backport。它叫ThreeTenABP。并确保使用子包从org.threeten.bp导入日期和时间类。 在上面的代码中,我使用来自后台端口的DateTimeUtils从Instant转换为Date。如果您的Android版本内置了java.time,请改用Date.fromstartOfDayInDefaultZone进行此转换

链接 解释如何使用java.time。 ,其中首次描述了java.time。 ,java.time的后端口到JSR-310的Java6和Java7。 ,Android版Three Ten Backport ,解释得非常透彻。
考虑扔掉长期过时和臭名昭著的简单的格式和朋友,并添加到Android项目中,以便使用JavaTime-现代java日期和时间API。和你一起工作真是太好了。现代的LocalDate可能会解决您的问题,因为它是一个没有时区的日期。我们在讨论吗?从文档中可以看出,它没有setDate方法。按照我的阅读方式,您需要使用updateDate.Thankyou Ole V.V,我使用的是自定义日期选择器,因此它有setDatedate方法。
    Instant startOfDayInDefaultZone = date.atStartOfDay(ZoneId.systemDefault())
            .toInstant();
    Date oldFashionedDate = DateTimeUtils.toDate(startOfDayInDefaultZone);
    System.out.println(oldFashionedDate);