Этот вопрос довольно близок к моему, однако я считаю, что ответ мне не подходит. У меня есть метка времени Long.
ts = 1362156863140L
Поскольку он длинный, я считаю его наивной временной меткой часового пояса, верно? Это отметка времени по местному времени в Кельне - UTC + 0200 (CET). Поэтому, когда я конвертирую его в метку времени с учетом часового пояса String, я хочу получить:
2013-03-01T14:54:23.140Z
или же
2013-03-01T16:54:23.140+02:00
Я использую решение из ответа в начале своего вопроса:
Instant.ofEpochMilli(timestamp).atOffset(ZoneOffset.of("+2"));
который возвращает:
2013-03-01T18:54:23.140+02:00
другой часовой пояс:
Instant.ofEpochMilli(timestamp).atOffset(ZoneOffset.of("Z"));
возвращает:
2013-03-01T16:54:23.140Z
Таким образом, эти методы на самом деле не изменяют часовой пояс, они просто изменяют представление временной метки. Я также попробовал другой метод:
OffsetDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.of("UTC"));
Но результаты точно такие же. Это решения был полезен, но оригинальный подход:
int offset = TimeZone.getTimeZone("Europe/Amsterdam").getRawOffset();
long newTime = timestamp - offset;
не считает летнее / зимнее время. И предлагаемые ответы используют класс Calendar, который устарел для JDK8. Что работает и достаточно очевидно:
OffsetDateTime.ofInstant(Instant.ofEpochMilli(Timestamp), ZoneId.of("UTC")).minusSeconds(7200);
Но это определенно неправильный способ сделать это, так как я могу сделать это с часовым поясом?
Как преобразовать этот 1362156863140L в этот 2013-03-01T14: 54: 23.140Z
«Поскольку это долго, я считаю это наивной временной меткой часового пояса». Я бы сказал наоборот. Учитывая, что long не может (легко) содержать информацию о часовом поясе, его нельзя хранить таким образом. Длинная метка времени должна быть моментом времени независимо от часового пояса (то есть метка времени Unix).
Это то, что я получаю для вашего значения метки времени ввода. 2013-03-01T21:24:23.140
Либо ваши предположения неверны, либо неверна ваша длинная ценность. Длинное значение, подобное вашему, обычно обозначает количество миллисекунд с эпохи 1 января 1970 года, 00:00 UTC. При таком понимании ваше длинное значение обозначает 2013-03-01T16:54:23.140Z, а не 2013-03-01T14:54:23.140Z (Z означает UTC). Если кто-то дал вам длинную ценность и имел в виду последнее, он сделал что-то нестандартным образом, что обязательно вызовет путаницу. А если так, то я не знаю, как бы они отнеслись к летнему времени, поэтому я также не могу сказать вам, как вы должны справиться с этим.




Я полагаю, что метка времени находится в UTC, и вам нужно изменить метку времени на CET. Взгляните на метод withZoneSameInstant(), может быть полезным.
long timeStamp = 1362156863140L;
ZoneId sourceZone = ZoneId.of("UTC");
ZoneId targetZone = ZoneId.of("CET");
String s = ZonedDateTime.ofInstant(Instant.ofEpochMilli(timeStamp), sourceZone)
.withZoneSameLocal(targetZone)
.toString();
System.out.println(s);
Наконец-то я использовал это: Instant.ofEpochMilli(timestamp).atOffset(ZoneOffset.of("Z")).withOffsetSameLocal(ZoneOffset.of("+2"));, но я до сих пор не знаю, как вести себя в летнее время.
Не полагайтесь на трехбуквенные сокращения часовых поясов, они не стандартизированы и не уникальны. На время в Кельне / Кельне я предлагаю ZoneId.of("Europe/Berlin"). Ваш код отражает хорошее предположение о том, как интерпретировать длинное значение спрашивающего, но мы не можем быть уверены в этом.
@ Charlie4fun ZonedDateTime обрабатывает летнее / зимнее время автоматически, насколько я знаю, но вам следует использовать ZoneId, а не смещения вроде "+2"
Ваш вопрос слишком общий? Скажите нам, что именно вам нужно?