17

我有格式为 20Jan2013、08Aug2012 等的日期,它们有自己的特定时区。例如,2013 年 1 月 20 日的时区 ID 可能是澳大利亚/墨尔本,而 08Aug2012 的时区 ID 可能是欧洲/伦敦。我想要做的是,根据这些时区和日期,计算给定日期该时区的 UTC 偏移量。到目前为止,我已经想出了这个:

DateTimeFormatter dtf = DateTimeFormat.forPattern("ZZ");
DateTimeFormatter dtf1 = DateTimeFormat.forPattern("ddMMMYYYY");

DateTimeZone zone = DateTimeZone.forID("Australia/Melbourne");  

DateTime thisDate = dtf1.parseDateTime("30Jul2013");                                            
System.out.println("\nZone: " + thisDate.withZone(zone));

这给了我输出:

Zone: 2013-07-30T00:00:00.000+10:00

这是正确的,但我想从中提取 UTC 偏移量,在本例中为 +10:00。我一直在寻找方法来做到这一点,但找不到任何东西。有什么办法可以做到这一点吗?我看到的唯一选择是将输出转换为字符串并使用子字符串方法获取 UTC 偏移量。

上面的代码确实考虑了 DST(夏令时)。例如,如果我有: DateTime thisDate = dtf1.parseDateTime("30Jan2013");

输出将是:2013-01-30T00:00:00.000+11:00

(结束时 +11:00 而不是 +10:00)

所以基本上我需要做的就是找到一种从 2013-07-30T00:00:00.000+11:00 中提取 +11:00 的方法。请帮忙!

4

5 回答 5

15

获取时区名称和小时偏移量的简单方法

public static String getCurrentTimeZoneOffset() {
    DateTimeZone tz = DateTimeZone.getDefault();
    Long instant = DateTime.now().getMillis();

    String name = tz.getName(instant);

    long offsetInMilliseconds = tz.getOffset(instant);
    long hours = TimeUnit.MILLISECONDS.toHours( offsetInMilliseconds );
    String offset = Long.toString( hours );

    return name + " (" + offset + " Hours)";
    // Example: "Mountain Standard Time (-7 Hours)"
}

几个警告:

  • DateTimeZone这从JodaTime获取默认值。您可以对其进行修改以接受传递给该方法的特定 DateTimeZone。
  • 这会以“山地标准时间(-7 小时) ”之类的格式返回它,但您可以很容易地按照您认为合适的格式对其进行格式化。

希望有帮助。

J.P

于 2014-01-29T02:11:55.160 回答
4

为了让 Joda 给出正确的偏移量,您必须提供一个日期时间瞬间。没有日期时间瞬间,就不可能计算偏移量,因为我们有不同的偏移量(夏令时)。这就是我将如何使用 Joda 以 + HH:mm 格式获取偏移量:

    int offsetInMillis = DateTimeZone.forID(zoneId).getOffset(new DateTime().getMillis());
    String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000),
            Math.abs((offsetInMillis / 60000) % 60));
    offset = (offsetInMillis >= 0 ? "+" : "-") + offset; 
于 2015-02-09T20:11:58.903 回答
3

If you just need the timezone offset, use DateTimeZone.forID() to get the time zone and then tz.getOffset(instant) to get the offset to UTC in milliseconds.

It may look odd that you need an instant to calculate the offset to UTC but this is necessary to take Daylight Savings into account as well as changes in the timezone. Yes, countries change their timezones once in a while:

Why does timezone data change?

Timezone settings are adopted locally, and there is no world timezone authority.

EDIT This gives you the correct result:

    DateTimeFormatter dtf1 = DateTimeFormat.forPattern("ddMMMYYYY");

    DateTimeZone zone = DateTimeZone.forID("Australia/Melbourne");  

    DateTime thisDate = dtf1.parseDateTime("30Jul2013").withZone(zone);                                            
    assertEquals( 10 * CommonConstants.MILLISECONDS_PER_HOUR,
        zone.getOffset( thisDate ) );

thisDate.get

于 2013-01-30T11:18:44.193 回答
2

Java 8引入了更好的日期和时间处理,以解决该语言先前在该领域的一些限制。我的一些项目已经开始使用它而不是 Joda。

使用 java.time 包:

    ZonedDateTime dateTime = LocalDate.of(2013 , 1 , 20).atStartOfDay( ZoneId.of("Australia/Melbourne"));
    ZoneOffset zo = dateTime.getOffset();
    int offset = zo.getTotalSeconds();

    long hours = TimeUnit.SECONDS.toHours(offset);
    long minutes = TimeUnit.SECONDS.toMinutes(offset % 3600);

小时变量设置为 11,分钟设置为 0。

它还计算部分小时时区的分钟偏移量,例如加拿大东部的纽芬兰和拉布拉多:

ZonedDateTime dateTime = LocalDate.of(2013, 1, 20).atStartOfDay( ZoneId.of("Canada/Newfoundland"));

在这种情况下,偏移量是-03:30(比 UTC 晚三个半小时)、 -3hoursminutes-30。

对于字符串表示形式,而不是整数小时和分钟数,请使用 ZoneOffset 的 toString() 方法。所以对于上面的例子,使用:

String offsetString = zo.toString();
于 2017-05-11T21:55:06.533 回答
0

当您知道偏移量和时间戳时,为了获得当前时间,您可以使用

 public static String formatMonthDayMinuteByGivenUtcOffset(long timestamp, int offset) {
        return JODA_FORMATTER.print(createDateTime(timestamp, offset));
    }
于 2017-04-28T14:53:33.037 回答