Получить значение смещения TimeZone из TimeZone без имени TimeZone
Мне нужно сохранить часовой пояс телефона в формате [+/-] чч: мм
Я использую класс TimeZone, чтобы справиться с этим, но единственный формат, который я могу получить, является следующим:
PST -05:00
GMT +02:00
Я бы предпочел не подставлять результат, есть ли какой-либо ключ или флаг опции, который я могу установить, чтобы получить только значение, а не имя этого часового пояса (GMT/CET/PST...)?
8 ответов
Мне нужно сохранить часовой пояс телефона в формате [+/-] чч: мм
Нет, ты не Смещения само по себе недостаточно, вам нужно хранить полное имя / идентификатор часового пояса. Например, я живу в Осло, где мое текущее смещение составляет +02:00, но зимой (из-за dst) это +01:00. Точное переключение между стандартным и летним временем зависит от факторов, которые вы не хотите исследовать.
Так что вместо хранения + 02:00
(или это должно быть + 01:00
?) Я храню "Europe/Oslo"
в моей базе данных. Теперь я могу восстановить полную конфигурацию, используя:
TimeZone tz = TimeZone.getTimeZone("Europe/Oslo")
Хотите знать, какое у меня смещение часового пояса сегодня?
tz.getOffset(new Date().getTime()) / 1000 / 60 //yields +120 minutes
Однако то же самое в декабре:
Calendar christmas = new GregorianCalendar(2012, DECEMBER, 25);
tz.getOffset(christmas.getTimeInMillis()) / 1000 / 60 //yields +60 minutes
Достаточно сказать: сохраняйте имя или идентификатор часового пояса, и каждый раз, когда вы хотите отобразить дату, проверяйте текущее смещение (сегодня), а не сохраняйте фиксированное значение. Ты можешь использовать TimeZone.getAvailableIDs()
перечислить все поддерживаемые идентификаторы часовых поясов.
@MrBean - у меня была похожая ситуация, когда мне приходилось вызывать сторонний веб-сервис и передавать текущее смещение часового пояса устройства 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;
}
С java8 теперь вы можете использовать
Integer offset = ZonedDateTime.now().getOffset().getTotalSeconds();
получить текущее смещение системного времени от UTC. Затем вы можете преобразовать его в любой формат, который вы хотите. Нашел это полезным для моего случая. Пример: https://docs.oracle.com/javase/tutorial/datetime/iso/timezones.html
В Java 8 этого можно добиться, выполнив следующий код.
TimeZone tz = TimeZone.getDefault();
String offsetId = tz.toZoneId().getRules().getStandardOffset(Instant.now()).getId();
и offsetId
будет что-то вроде +01:00
Обратите внимание на функцию getStandardOffset
нужен Instant
как параметр. Это конкретный момент времени, в который вы хотите проверить смещение данного часового пояса, поскольку смещение часового пояса может меняться во времени. По причине того, что в некоторых районах действует летнее время.
Я думаю, что это причина, по которой @Tomasz Nurkiewicz рекомендует не сохранять смещение напрямую в формате часов со знаком, а проверять смещение каждый раз, когда оно вам нужно.
ZoneId here = ZoneId.of("Europe/Kiev");
ZonedDateTime hereAndNow = Instant.now().atZone(here);
String.format("%tz", hereAndNow);
даст вам стандартизированное строковое представление, как "+0300"
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
Узнайте больше о современном API даты и времени* из Trail: Date Time .
* По любой причине, если вам нужно придерживаться Java 6 или Java 7, вы можете использовать ThreeTen-Backport, который поддерживает большую часть функциональности java.time для Java 6 и 7. Если вы работаете над проектом Android и своим Android API уровень по-прежнему не соответствует Java-8, проверьте API-интерфейсы Java 8+, доступные через десугаринг, и Как использовать ThreeTenABP в Android Project .
Мы можем легко получить миллисекундное смещение TimeZone
только с TimeZone
экземпляр и System.currentTimeMillis()
, Затем мы можем конвертировать из миллисекунд в любую единицу времени, используя TimeUnit
учебный класс.
Вот так:
public static int getOffsetHours(TimeZone timeZone) {
return (int) TimeUnit.MILLISECONDS.toHours(timeZone.getOffset(System.currentTimeMillis()));
}
Я знаю, что это старый, но я решил дать свой вклад. Я должен был сделать это для проекта на работе, и это было мое решение.
У меня есть объект Building, который включает в себя часовой пояс, используя класс TimeZone, и хотел создать поля zoneId и смещения в новом классе.
Так что я сделал создать:
private String timeZoneId;
private String timeZoneOffset;
Затем в конструкторе я передал объект Building и установил эти поля следующим образом:
this.timeZoneId = building.getTimeZone().getID();
this.timeZoneOffset = building.getTimeZone().toZoneId().getId();
Поэтому timeZoneId может равняться чему-то вроде "EST", а timeZoneOffset может равняться что-то вроде "-05:00"
Я бы не хотел, чтобы вы не