【问题标题】:I'm unable to get the right timezone offset with daylight我无法在日光下获得正确的时区偏移
【发布时间】:2021-05-28 14:35:33
【问题描述】:

我在 android 中遇到了日光问题,时间应该是 +3 GMT/UTC 但我只得到 +2。有什么解决方案还是我无法处理?请在下面找到我的代码

  TimeZone.getDefault().useDaylightTime();
  SimpleDateFormat df = new SimpleDateFormat("HH:mm",Locale.ENGLISH); //"2021-02-18T11:00:00"
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        return df.format(calendar.getTime());

请注意,夏令时偏移量返回零。我应该怎么做才能处理日光? 另一个注意我的时间是约旦/安曼, 在冬天这应该返回+2,但在夏天它应该返回+3

【问题讨论】:

  • 我建议你不要使用TimeZoneSimpleDateFormatCalendar。这些类设计糟糕且过时,SimpleDateFormat 特别是出了名的麻烦。而是使用来自java.time, the modern Java date and time APIZoneIdLocalTime
  • 切换到java.time API。出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7。如果您正在为Android 项目且您的 Android API 级别仍不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project
  • @OleV.V.感谢您的建议,但实际上旧的 android 设备不支持 java 8
  • @BasilBattikhi 不直接,你是对的。但只要您使用的是 Android Gradle 插件 4.0 或更高版本,使用 coreLibraryDesugaring 您就可以直接使用 java.time。如果不是,请按照我在下面的答案和那里的链接中所述使用 ThreeTen Backport。

标签: java android date simpledateformat


【解决方案1】:

java.time

考虑使用现代 Java 日期和时间 API java.time 来处理您的日期和时间工作。让我们首先为您想要的时间格式声明一个格式化程序:

private static final DateTimeFormatter TIME_FORMATTER
        = DateTimeFormatter.ofPattern("HH:mm", Locale.ENGLISH);

现在您可以用这种方式从Calendar 格式化时间:

    // Assume you are getting a Calendar from somewhere
    Calendar calendar = new GregorianCalendar();
    
    ZonedDateTime dateTime = calendar.toInstant().atZone(ZoneId.systemDefault());
    String dateTimeString = dateTime.format(TIME_FORMATTER);
    
    System.out.println(dateTimeString);

我刚才跑了代码,也就是UTC时间16:33或者约旦时间19:33。输出是:

19:33

如果您不依赖从某个地方获取老式的Calendar,它可能会更简单、更干净。例如,要获取您所在时区的当前时间:

    String timeString
            = LocalTime.now(ZoneId.systemDefault()).format(TIME_FORMATTER);
    System.out.println(timeString);

你的代码出了什么问题?

您将SimpleDateFormat 的时区设置为UTC。因此,无论您的默认时区如何,都会打印 UTC 时间。而且由于 UTC 没有夏令时 (DST),因此没有考虑到这一点。

顺便说一句,你的这个方法调用什么都不做:

    TimeZone.getDefault().useDaylightTime();

来自文档:

返回:

true 如果这个TimeZone 使用夏令时,false, 否则。

所以该方法不会改变任何东西,当然也不会改变 UTC 时区。它只查询提到的时区是否使用夏令时(夏令时)。因此,由于亚洲/安曼时区确实如此,因此在您的情况下它应该返回 true

问:java.time 不需要 Android API 26 级吗?

java.time 在较旧和较新的 Android 设备上都能很好地工作。它只需要至少 Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 起)中,现代 API 是内置的。
  • 在非 Android Java 6 和 7 中,获取 ThreeTen Backport,这是现代类的后向端口(JSR 310 的 ThreeTen;请参阅底部的链接)。
  • 在较旧的 Android 上,请使用脱糖或 Android 版本的 ThreeTen Backport。它被称为 ThreeTenABP。在后一种情况下,请确保从 org.threeten.bp 导入日期和时间类以及子包。

链接

【讨论】:

  • 感谢您的回答,因为我说旧的 android 设备不支持 java 8,所以我不能使用 toInstant
  • @BasilBattikhi 不直接,你是对的。但只要您使用的是 Android Gradle 插件 4.0 或更高版本,使用 coreLibraryDesugaring 您就可以直接使用 java.time。如果不是,请按照答案和链接中的说明使用 ThreeTen Backport。
猜你喜欢
  • 2015-07-20
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 2019-03-14
相关资源
最近更新 更多