我的日期格式为2013年1月,2012年8月8日等,具有自己的特定时区。例如,20Jan2013 的时区 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。请帮忙!
获取时区名称和偏移量(以小时为单位)的简单方法
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)"
}
几个注意事项:
- 这将从 JodaTime 获取默认
DateTimeZone
。您可以修改它以接受传递到该方法中的特定日期时区。 - 这会以"山区标准时间(-7 小时)"之类的格式返回它,但您可以轻松设置它所需的格式。
希望有帮助。
太平绅士
为了让 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;
如果只需要时区偏移量,请使用 DateTimeZone.forID()
获取时区,然后tz.getOffset(instant)
获取 UTC 偏移量(以毫秒为单位)。
您需要一个即时来计算到 UTC 的偏移量可能看起来很奇怪,但这对于考虑夏令时以及时区的变化是必要的。是的,国家/地区偶尔会更改时区:
为什么时区数据会更改?
时区设置在本地采用,没有世界时区机构。
编辑 这将为您提供正确的结果:
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 ) );
这个日期.get
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 晚三个半小时),hours
为 -3,minutes
为 -30。
对于 String 表示形式,而不是整数小时数和分钟数,请使用 ZoneOffset 的 toString() 方法。因此,对于上面的示例,请使用:
String offsetString = zo.toString();
当你知道偏移量和时间戳时,为了获得当前时间,你可以使用
public static String formatMonthDayMinuteByGivenUtcOffset(long timestamp, int offset) {
return JODA_FORMATTER.print(createDateTime(timestamp, offset));
}