Преобразовать дату / время для заданного часового пояса - java
Я хочу преобразовать эту отметку времени GMT в GMT + 13:
2011-10-0603:35:05
Я перепробовал около 100 различных комбинаций DateFormat, TimeZone, Date, GregorianCalendar и т.д. чтобы попытаться выполнить эту ОЧЕНЬ простую задачу.
Этот код делает то, что я хочу для ТЕКУЩЕГО ВРЕМЕНИ:
Но я хочу установить время, а не использовать текущее время.
Я обнаружил, что каждый раз, когда я пытаюсь установить время следующим образом:
calendar.setTime(newDate(1317816735000L));
используется часовой пояс локального компьютера. Почему это? Я знаю, что когда "new Date ()" возвращает время UTC + 0, так почему же, когда вы устанавливаете время в миллисекундах, оно больше не предполагает, что время указано в UTC?
Возможно ли:
Установка времени для объекта (календарь / Дата / Временная метка)
(Возможно) Установить часовой пояс начальной временной метки (calendar.setTimeZone(...))
Отформатируйте отметку времени с помощью нового часового пояса (formatter.setTimeZone(...)))
Возвращает строку с указанием времени в новом часовом поясе. (formatter.format(calendar.getTime()))
//Here you say to java the initial timezone. This is the secret sdf.setTimeZone(TimeZone.getTimeZone("UTC")); //Will print in UTC System.out.println(sdf.format(calendar.getTime()));
//Here you set to your timezone sdf.setTimeZone(TimeZone.getDefault()); //Will print on your default Timezone System.out.println(sdf.format(calendar.getTime()));
Ответ 2
Понимание того, как работает компьютерное время, очень важно. С учетом сказанного я согласен, что если API создан, чтобы помочь вам обрабатывать компьютерное время как реальное, то оно должно работать таким образом, чтобы вы могли обрабатывать его как реальное. По большей части это так, но есть некоторые серьезные упущения, на которые действительно нужно обратить внимание.
В любом случае, я отвлекся!! Если у вас есть смещение UTC (лучше работать со смещением UTC, чем GMT), вы можете рассчитать время в миллисекундах и добавить это к вашей временной метке. Обратите внимание, что временная метка SQL может отличаться от временной метки Java, поскольку способ вычисления истечения из эпохи не всегда одинаков - зависит от технологий баз данных, а также операционных систем.
I would advise you to use System.currentTimeMillis() as your time stamps as these can be processed more consistently in java without worrying about converting SQL Timestamps to java Date objects etc.
To calculate your offset you can try something like this:
В вопросе и большинстве ответов используются устаревшие устаревшие классы даты и времени из самых ранних версий Java. Эти старые классы оказались хлопотными и сбивающими с толку. Избегайте их. Вместо этого используйте классы java.time .
ISO 8601
Ваша входная строка почти соответствует стандартному формату ISO 8601. Просто замените ПРОБЕЛ посередине на T.
Теперь выполняется синтаксический анализ как LocalDateTime поскольку во входных данных отсутствует какая-либо информация о смещении от UTC или часового пояса. В A LocalDateTime нет понятия смещения или часового пояса, поэтому оно не отражает фактический момент на временной шкале.
LocalDateTimeldt= LocalDateTime.parse( input );
ZoneOffset
Вы, кажется, говорите, что из бизнес-контекста вы знаете, что назначение этой строки - представлять момент, который на 13 часов опережает UTC. Итак, мы создаем экземпляр ZoneOffset.
ZoneOffsetoffset= ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe.
OffsetDateTime
Примените это для получения OffsetDateTime объекта. Это становится актуальным моментом на временной шкале.
OffsetDateTimeodt= ldt.atOffset( offset);
ZoneId
Но затем вы упомянули Новую Зеландию. Значит, вы имели в виду конкретный часовой пояс. Часовой пояс - это смещение от UTC плюс набор правил для обработки аномалий, таких как переход на летнее время (DST). Таким образом, мы можем указать ZoneId в ZonedDateTime, а не просто смещение.
Укажите правильное название часового пояса. Никогда не используйте 3-4-буквенные сокращения, такие как EST или IST, поскольку они не являются настоящими часовыми поясами, не стандартизированы и даже не уникальны (!). Например, Pacific/Auckland.
ZoneIdz= ZoneId.of( "Pacific/Auckland" );
ZonedDateTime
Примените ZoneId.
ZonedDateTimezdt= ldt.atZone( z );
Вы можете легко перейти в другую зону в тот же самый момент на временной шкале.
ZoneIdzParis= ZoneId.of( "Europe/Paris" ); ZonedDateTimezdtParis= zdt.withZoneSameInstant( zParis ); // Same moment in time, but seen through lens of Paris wall-clock time.
Отсчет от эпохи
Я настоятельно не рекомендую обрабатывать значения даты и времени как отсчет от эпохи, например миллисекунд от начала 1970 года по Гринвичу. Но если необходимо, создайте Instant из такого числа.
Затем при желании назначьте часовой пояс, как показано выше, для отклонения от UTC.
ZoneIdz= ZoneId.of( "Pacific/Auckland" ); ZonedDateTimezdt= instant.atZone( z );
Ваше значение 1_317_816_735_000L равно:
2011-10-05T12:12:15Z (Ср. 05 окт. 2011 г. 12:12:15 GMT)
2011-10-06T01:12:15+13:00[Pacific/Auckland] (Четверг, 06 октября 2011 г., 01:12:15, Окленд, Новая Зеландия).
Генерация строк
Чтобы сгенерировать строку в стандартном формате ISO 8601, просто вызовите toString. Обратите внимание, что ZonedDateTime разумно расширяет стандартный формат, добавляя название часового пояса в квадратных скобках.
Stringoutput= zdt.toString();
Для других форматов выполните поиск в Stack Overflow для DateTimeFormatter class . Это уже обсуждалось много раз.
Localel=newLocale( "en" , "NZ" ); DateTimeFormatterf= DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l ); Stringoutput= zdt.format( f );
Обратите внимание, что часовой пояс не имеет ничего общего с locale. Вы можете отобразить Europe/Paris дату и время в соответствии с японским языком и культурными нормами или Asia/Kolkata дату и время в соответствии с португальским языком и культурными нормами Бразилии.
О java.time
Платформа java.time встроена в Java 8 и более поздние версии. Эти классы заменяют старые классы даты и времени, такие как java.util.Date, .Calendar, & java.text.SimpleDateFormat.
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является испытательным полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и другие.
Ответ 4
Как всегда, я рекомендую прочитать эту статью о дате и времени в Java, чтобы вы ее поняли.
Основная идея заключается в том, что "под капотом" все выполняется в миллисекундах UTC с момента начала эпохи. Это означает, что проще всего работать вообще без использования часовых поясов, за исключением форматирования строк для пользователя.
Поэтому я бы пропустил большинство предложенных вами шагов.
Установите время для объекта (дата, календарь и т.д.).
Установите часовой пояс для объекта форматирования.
Возвращает строку из форматера.
В качестве альтернативы вы можете использовать Joda time. Я слышал, что это гораздо более интуитивно понятный datetime API.