60

我需要以 [+/-]hh:mm 格式保存手机的时区

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

PST -05:00
GMT +02:00

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

4

8 回答 8

105

我需要以 [+/-]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。

于 2012-07-09T16:46:00.707 回答
73

@MrBean - 我处于类似的情况,我必须调用第 3 方 Web 服务并以 +/-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;
} 
于 2013-05-21T22:53:10.200 回答
20

现在有了java8,你可以使用

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

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

于 2017-12-07T18:50:52.843 回答
7

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

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

并且offsetId将类似于 +01:00

请注意该函数getStandardOffset需要一个Instant作为参数。这是您要检查给定时区偏移量的特定时间点,因为时区的偏移量可能会在 time 期间发生变化。由于某些地区有夏令时

我认为这就是为什么@Tomasz Nurkiewicz 建议不要直接以带符号的小时格式存储偏移量,而是在每次需要时检查偏移量的原因。

于 2019-09-16T09:14:52.077 回答
5
ZoneId here = ZoneId.of("Europe/Kiev");
ZonedDateTime hereAndNow = Instant.now().atZone(here);
String.format("%tz", hereAndNow);

会给你一个标准化的字符串表示,比如“+0300”

于 2018-06-29T15:54:28.797 回答
4

我们可以很容易地得到 a 的毫秒偏移量,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(zo.getTotalSeconds());
}
于 2018-11-20T10:07:33.143 回答
3

java.time:现代日期时间 API

您可以使用ZonedDateTime#getOffset.

请注意,观察DST的时区的偏移量会根据 DST的变化而变化。对于其他地方(例如印度),它保持不变。因此,建议提及显示时区偏移量的时刻。提到了一个时刻Instant.now(),它表示 UTC 中的日期时间(由Z它表示代表 Zulu 并指定+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  

Trail: Date Time了解有关现代日期时间 API *的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,则可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目和 Android API 工作level 仍然不符合 Java-8,请检查Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

于 2021-05-05T22:18:40.793 回答
2

我知道这是旧的,但我想我会给出我的意见。我必须为工作中的一个项目这样做,这就是我的解决方案。

我有一个 Building 对象,其中包含使用 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”之类的东西

我不想你可能不会

于 2017-04-10T15:21:42.123 回答