1. Overview
1.概述
Whenever we deal with times and dates, we need a frame of reference. The standard for that is UTC, but we also see GMT in some applications.
每当我们处理时间和日期时,我们需要一个参考框架。这方面的标准是UTC,但我们也在一些应用中看到GMT。
In short, UTC is the standard, while GMT is a time zone.
简而言之,UTC是标准,而GMT是一个时区。
This is what Wikipedia tells us regarding what to use:
这是维基百科告诉我们的关于使用的内容。
For most purposes, UTC is considered interchangeable with Greenwich Mean Time (GMT), but GMT is no longer precisely defined by the scientific community.
在大多数情况下,UTC被认为可与格林威治时间(GMT)互换,但格林威治时间已不再被科学界精确定义。
In other words, once we compile a list with time zone offsets in UTC, we’ll have it for GMT as well.
换句话说,一旦我们编制了一个包含UTC时区偏移的列表,我们也会有GMT的时区偏移。
First, we’ll have a look at the Java 8 way of achieving this and then we’ll see how we can get the same result in Java 7.
首先,我们来看看Java 8的实现方式,然后再看看我们如何在Java 7中得到同样的结果。
2. Getting a List of Zones
2.获得一个区的清单
To start with, we need to retrieve a list of all defined time zones.
首先,我们需要检索一个所有定义的时区列表。
For this purpose, the ZoneId class has a handy static method:
为此,ZoneId类有一个方便的静态方法。
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
Then, we can use the Set to generate a sorted list of time zones with their corresponding offsets:
然后,我们可以使用Set来生成一个经过排序的时区列表,其中包括其相应的偏移量。
public List<String> getTimeZoneList(OffsetBase base) {
LocalDateTime now = LocalDateTime.now();
return ZoneId.getAvailableZoneIds().stream()
.map(ZoneId::of)
.sorted(new ZoneComparator())
.map(id -> String.format(
"(%s%s) %s",
base, getOffset(now, id), id.getId()))
.collect(Collectors.toList());
}
The method above uses an enum parameter which represents the offset we want to see:
上面的方法使用了一个enum参数,代表我们想看到的偏移量。
public enum OffsetBase {
GMT, UTC
}
Now let’s go over the code in more detail.
现在让我们更详细地了解一下这段代码。
Once we’ve retrieved all available zone IDs, we need an actual time reference, represented by LocalDateTime.now().
一旦我们检索到所有可用的区域ID,我们需要一个实际的时间参考,用LocalDateTime.now()表示。
After that, we use Java’s Stream API to iterate over each entry in our set of time zone String id’s and transform it into a list of formatted time zones with the corresponding offset.
之后,我们使用Java的Stream API来迭代时区String id’s 集合中的每个条目,并将其转化为一个带有相应偏移量的格式化时区列表。
For each of these entries, we generate a ZoneId instance with map(ZoneId::of).
对于每个条目,我们用map(ZoneId::of)生成一个ZoneId实例。
3. Getting Offsets
3.获得抵偿
We also need to find actual UTC offsets. For example, in the case of Central European Time, the offset would be +01:00.
我们还需要找到实际的UTC偏移量。例如,在中欧时间的情况下,偏移量将是+01:00.。
To get the UTC offset for any given zone, we can use LocalDateTime’s getOffset() method.
为了获得任何特定区域的UTC偏移量,我们可以使用LocalDateTime的getOffset()方法。
Also note that Java represents +00:00 offsets as Z.
还要注意,Java将+00:00偏移量表示为Z。
So, to have a consistent looking String for time zones with the zero offset, we’ll replace Z with +00:00:
因此,为了使时区与零点偏移的String看起来一致,我们将用+00:00:取代Z。
private String getOffset(LocalDateTime dateTime, ZoneId id) {
return dateTime
.atZone(id)
.getOffset()
.getId()
.replace("Z", "+00:00");
}
4. Making Zones Comparable
4.使各区具有可比性
Optionally, we can also sort the time zones according to offset.
作为选择,我们还可以根据偏移量对时区进行排序。
For this, we’ll use a ZoneComparator class:
为此,我们将使用一个ZoneComparator类。
private class ZoneComparator implements Comparator<ZoneId> {
@Override
public int compare(ZoneId zoneId1, ZoneId zoneId2) {
LocalDateTime now = LocalDateTime.now();
ZoneOffset offset1 = now.atZone(zoneId1).getOffset();
ZoneOffset offset2 = now.atZone(zoneId2).getOffset();
return offset1.compareTo(offset2);
}
}
5. Displaying Time Zones
5.显示时区
All that’s left to do is putting the above pieces together by calling the getTimeZoneList() method for each OffsetBase enum value and displaying the lists:
剩下的就是通过为每个OffsetBase枚举值调用getTimeZoneList()方法,将上述部分组合起来,并显示列表。
public class TimezoneDisplayApp {
public static void main(String... args) {
TimezoneDisplay display = new TimezoneDisplay();
System.out.println("Time zones in UTC:");
List<String> utc = display.getTimeZoneList(
TimezoneDisplay.OffsetBase.UTC);
utc.forEach(System.out::println);
System.out.println("Time zones in GMT:");
List<String> gmt = display.getTimeZoneList(
TimezoneDisplay.OffsetBase.GMT);
gmt.forEach(System.out::println);
}
}
When we run the above code, it’ll print the time zones for UTC and GMT.
当我们运行上述代码时,它将打印出UTC和GMT的时区。
Here’s a snippet of how the output will look like:
下面是输出结果的一个片段,看起来像。
Time zones in UTC:
(UTC+14:00) Pacific/Apia
(UTC+14:00) Pacific/Kiritimati
(UTC+14:00) Pacific/Tongatapu
(UTC+14:00) Etc/GMT-14
6. Java 7 and Before
6.Java 7及之前
Java 8 makes this task easier by using the Stream and Date and Time APIs.
Java 8通过使用Stream和Date and Time API,使这项任务变得更加容易。
However, if we have a Java 7 and before a project, we can still achieve the same result by relying on the java.util.TimeZone class with its getAvailableIDs() method:
然而,如果我们有一个Java 7并在一个项目之前,我们仍然可以通过依靠java.util.TimeZone类及其getAvailableIDs()方法来实现同样的结果。
public List<String> getTimeZoneList(OffsetBase base) {
String[] availableZoneIds = TimeZone.getAvailableIDs();
List<String> result = new ArrayList<>(availableZoneIds.length);
for (String zoneId : availableZoneIds) {
TimeZone curTimeZone = TimeZone.getTimeZone(zoneId);
String offset = calculateOffset(curTimeZone.getRawOffset());
result.add(String.format("(%s%s) %s", base, offset, zoneId));
}
Collections.sort(result);
return result;
}
The main difference with the Java 8 code is the offset calculation.
与Java 8代码的主要区别是偏移量的计算。
The rawOffset we get from TimeZone()‘s getRawOffset() method expresses the time zone’s offset in milliseconds.
我们从TimeZone()的getRawOffset()方法中得到的rawOffset表示时区的偏移量,单位为毫秒。
Therefore, we need to convert this to hours and minutes using the TimeUnit class:
因此,我们需要使用TimeUnit类将其转换为小时和分钟。
private String calculateOffset(int rawOffset) {
if (rawOffset == 0) {
return "+00:00";
}
long hours = TimeUnit.MILLISECONDS.toHours(rawOffset);
long minutes = TimeUnit.MILLISECONDS.toMinutes(rawOffset);
minutes = Math.abs(minutes - TimeUnit.HOURS.toMinutes(hours));
return String.format("%+03d:%02d", hours, Math.abs(minutes));
}
7. Conclusion
7.结论
In this quick tutorial, we’ve seen how we can compile a list of all available time zones with their UTC and GMT offsets.
在这个快速教程中,我们已经看到了如何编制所有可用的时区及其UTC和GMT偏移量的列表。
And, as always, the full source code for the examples is available over on GitHub.
而且,像往常一样,这些例子的完整源代码可在GitHub上获得。