从TimeZone获取TimeZone偏移值而不使用TimeZone名称

时间:2012-07-09 16:43:25

标签: java timezone

我需要以[+/-] hh:mm

格式保存手机的时区

我正在使用TimeZone类来处理这个问题,但我能得到的唯一格式如下:

PST -05:00
GMT +02:00

我宁愿不对结果进行子串,是否有任何键或选项标志我可以设置为只获取值而不是该时区的名称(GMT / CET / PST ...)?

8 个答案:

答案 0 :(得分:82)

  

我需要以[+/-] hh:mm

格式保存手机的时区

不,你没有。抵消它本身是不够的,你需要存储整个时区名称/ ID。例如,我住在奥斯陆,我的当前偏移是+02:00,但在冬天(由于),它是+01:00。标准时间和夏令时之间的确切切换取决于您不想探索的因素。

所以我不是存储+ 02:00(或者应该是+ 01:00?)而是将"Europe/Oslo"存储在我的数据库中。现在我可以使用以下命令恢复完整配置:

TimeZone tz = TimeZone.getTimeZone("Europe/Oslo")

想知道我今天的时区偏移量是多少?

tz.getOffset(new Date().getTime()) / 1000 / 60   //yields +120 minutes

然而在12月也一样:

Calendar christmas = new GregorianCalendar(2012, DECEMBER, 25);
tz.getOffset(christmas.getTimeInMillis()) / 1000 / 60   //yields +60 minutes

足以说明:存储时区名称或ID,并且每次要显示日期时,请检查当前偏移(今天)是什么,而不是存储固定值。您可以使用TimeZone.getAvailableIDs()枚举所有支持的时区ID。

答案 1 :(得分:65)

@MrBean - 我遇到类似的情况,我不得不拨打第三方网络服务,并以+/- hh:mm的格式传递Android设备的当前时区偏移量。这是我的解决方案:

public static String getCurrentTimezoneOffset() {

    TimeZone tz = TimeZone.getDefault();  
    Calendar cal = GregorianCalendar.getInstance(tz);
    int offsetInMillis = tz.getOffset(cal.getTimeInMillis());

    String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000), Math.abs((offsetInMillis / 60000) % 60));
    offset = (offsetInMillis >= 0 ? "+" : "-") + offset;

    return offset;
} 

答案 2 :(得分:3)

现在使用java8,您可以使用

Integer offset  = ZonedDateTime.now().getOffset().getTotalSeconds();

从UTC获取当前系统时间偏移量。然后,您可以将其转换为您想要的任何格式。发现它对我的情况有用。 示例:https://docs.oracle.com/javase/tutorial/datetime/iso/timezones.html

答案 3 :(得分:3)

java.time:现代日期时间 API

您可以使用 ZonedDateTime#getOffset 获取时区的偏移量。

请注意,观察 DST 的时区的偏移量会随着 DST 的变化而变化。对于其他地方(例如印度),它保持不变。因此,建议提及显示时区偏移的时刻。一个时刻被称为 Instant.now(),它表示 UTC 中的日期时间(由 Z 表示,代表祖鲁语并指定 +00:00 小时的时区偏移量)。

显示 ZoneId.getAvailableZoneIds() 返回的所有时区的偏移量:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        // Test
        Instant instant = Instant.now();
        System.out.println("Timezone offset at " + instant);
        System.out.println("==============================================");
        ZoneId.getAvailableZoneIds()
            .stream()
            .sorted()
            .forEach(strZoneId -> System.out.printf("%-35s: %-6s%n",
                strZoneId, getTzOffsetString(ZoneId.of(strZoneId), instant)));
    }

    static String getTzOffsetString(ZoneId zoneId, Instant instant) {
        return ZonedDateTime.ofInstant(instant, zoneId).getOffset().toString();
    }
}

输出:

Timezone offset at 2021-05-05T21:45:34.150901Z
==============================================
Africa/Abidjan                     : Z     
Africa/Accra                       : Z     
Africa/Addis_Ababa                 : +03:00
...
...
...    
W-SU                               : +03:00
WET                                : +01:00
Zulu                               : Z  

modern date-time API 中了解有关 Trail: Date Time* 的更多信息。


* 出于任何原因,如果您必须坚持使用 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

答案 4 :(得分:2)

ZoneId here = ZoneId.of("Europe/Kiev");
ZonedDateTime hereAndNow = Instant.now().atZone(here);
String.format("%tz", hereAndNow);

将为您提供标准化的字符串表示形式,例如“ +0300”

答案 5 :(得分:1)

我知道这已经过时了,但我想我会给出我的意见。我必须为工作中的项目做这件事,这是我的解决方案。

我有一个Building对象,它使用TimeZone类包含Timezone,并希望在新类中创建zoneId和offset字段。

所以我做的是创造:

private String timeZoneId;
private String timeZoneOffset;

然后在构造函数中,我传入了Building对象并设置了这些字段:

this.timeZoneId = building.getTimeZone().getID();
this.timeZoneOffset = building.getTimeZone().toZoneId().getId();

所以timeZoneId可能等于" EST" timeZoneOffset可能等于" -05:00"

我不想你可能不会

答案 6 :(得分:1)

我们只需一个TimeZone实例和一个TimeZone就可以轻松获得System.currentTimeMillis()的毫秒偏移量。然后,我们可以使用TimeUnit类将毫秒转换为选择的任何时间单位。

像这样:

public static int getOffsetHours(TimeZone timeZone) {
    return (int) TimeUnit.MILLISECONDS.toHours(timeZone.getOffset(System.currentTimeMillis()));
}

或者如果您喜欢新的Java 8时间API

public static ZoneOffset getOffset(TimeZone timeZone) { //for using ZoneOffsett class
    ZoneId zi = timeZone.toZoneId();
    ZoneRules zr = zi.getRules();
    return zr.getOffset(LocalDateTime.now());
}

public static int getOffsetHours(TimeZone timeZone) { //just hour offset
    ZoneOffset zo = getOffset(timeZone);
    TimeUnit.SECONDS.toHours(so.getTotalSeconds());
}

答案 7 :(得分:1)

使用Java 8,您可以通过以下代码来实现。

    TimeZone tz = TimeZone.getDefault();
    String offsetId = tz.toZoneId().getRules().getStandardOffset(Instant.now()).getId();

offsetId类似于+01:00

请注意,函数getStandardOffset需要一个Instant作为参数。这是您要检查给定时区的偏移量的特定时间点,因为时区的偏移量可能在时间上有所不同。由于某些区域的原因,夏令时

我认为这就是@Tomasz Nurkiewicz命令不要直接以签名小时格式存储偏移量,而是在每次需要时检查偏移量的原因。