我正在显示一个日期。日期随设备更改的时区而变化。例如-时区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();
}
或
// 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);
我正在使用具有DatePicker
方法(而非setDate(date)
)的自定义android.widget.DatePicker
。
我已经检查了许多类似的问答,但是没有运气。谢谢
答案 0 :(得分:1)
使用java.util.Date
无法做到。尽管有类名Date
并不代表日期。这是一个时间点。因此,自创建Date
以来,JVM的默认时区可能已更改,因此无法检测创建Date
时使用的时区。您当然可以尝试所有可能的时区。通常,这会给您两个,偶尔三个日期。因为它在所有时区都不是同一日期。
由于Date
类的设计欠佳且已过时,因此听起来可能并不那么糟糕,所以您无论如何都不要使用它。
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月1日星期五欧洲中部时间
是的,java.time在较新和较旧的Android设备上均可正常运行。它只需要至少 Java 6 。
org.threeten.bp
导入日期和时间类。在上面的代码中,我使用反向端口中的DateTimeUtils
从Instant
转换为Date
。如果您的Android版本内置了java.time,请改用Date.from(startOfDayInDefaultZone)
进行转换。
java.time
。java.time
向Java 6和7(JSR-310的ThreeTen)的反向端口。