Я хочу преобразовать эту метку времени GMT в GMT + 13:
2011-10-06 03:35:05
Я пробовал около 100 различных комбинаций DateFormat, TimeZone, Date, GregorianCalendar и т.д., чтобы попытаться выполнить эту ОЧЕНЬ простую задачу.
Этот код делает то, что я хочу в ТЕКУЩЕЕ ВРЕМЯ:
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));
String newZealandTime = formatter.format(calendar.getTime());
Но я хочу установить время, а не использовать текущее время.
Я обнаружил, что каждый раз, когда я пытаюсь установить время следующим образом:
calendar.setTime(new Date(1317816735000L));
используется часовой пояс локального компьютера. Это почему? Я знаю, что когда «new Date ()» возвращает время UTC + 0, почему, когда вы устанавливаете время в миллисекундах, он больше не предполагает, что время находится в UTC?
Это возможно:
- Установите время на объекте (Calendar / Date / TimeStamp)
- (Возможно) Установите часовой пояс начальной отметки времени (calendar.setTimeZone (...))
- Отформатируйте метку времени с новым часовым поясом (formatter.setTimeZone (...)))
- Вернуть строку с новым временем часового пояса. (formatter.format (calendar.getTime ()))
Заранее благодарим за любую помощь: D
1317816735000L
это неправильная метка времени2011-10-06 03:35:05 GMT
. В остальном ваш подход правильный.java.util.Date
,java.util.Calendar
иjava.text.SimpleDateFormat
, теперь унаследованы , вытеснены классами java.time, встроенными в Java 8 и новее. См. Учебник Oracle .Ответы:
Для меня самый простой способ сделать это:
Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //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()));
источник
review
в очереди?date = sdf.parse(review);
sdf.parse(DateObject)
он не определен в java, который я используюJDK.1.7
.Понимание того, как работает компьютерное время, очень важно. С учетом сказанного я согласен с тем, что если API создается, чтобы помочь вам обрабатывать компьютерное время как реальное время, тогда он должен работать таким образом, чтобы вы могли рассматривать его как реальное время. По большей части это так, но есть некоторые серьезные упущения, которые требуют внимания.
В любом случае я отвлекся !! Если у вас есть смещение UTC (лучше работать в UTC, чем смещение по Гринвичу), вы можете рассчитать время в миллисекундах и добавить его к своей временной метке. Обратите внимание, что отметка времени SQL может отличаться от отметки времени Java, поскольку способ вычисления времени, прошедшего с эпохи, не всегда одинаков - это зависит от технологий баз данных, а также от операционных систем.
Я бы посоветовал вам использовать System.currentTimeMillis () в качестве меток времени, поскольку они могут обрабатываться более последовательно в java, не беспокоясь о преобразовании меток времени SQL в объекты даты Java и т. Д.
Чтобы рассчитать смещение, вы можете попробовать что-то вроде этого:
Long gmtTime =1317951113613L; // 2.32pm NZDT Long timezoneAlteredTime = 0L; if (offset != 0L) { int multiplier = (offset*60)*(60*1000); timezoneAlteredTime = gmtTime + multiplier; } else { timezoneAlteredTime = gmtTime; } Calendar calendar = new GregorianCalendar(); calendar.setTimeInMillis(timezoneAlteredTime); DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z"); formatter.setCalendar(calendar); formatter.setTimeZone(TimeZone.getTimeZone(timeZone)); String newZealandTime = formatter.format(calendar.getTime());
Надеюсь, это поможет!
источник
Как всегда, я рекомендую прочитать эту статью о дате и времени в Java, чтобы вы ее поняли.
Основная идея заключается в том, что «под капотом» все делается в миллисекундах UTC с начала эпохи. Это означает, что проще всего работать без использования часовых поясов, за исключением форматирования строки для пользователя.
Поэтому я бы пропустил большинство предложенных вами шагов.
В качестве альтернативы вы можете использовать время Joda . Я слышал, что это гораздо более интуитивно понятный API даты и времени.
источник
tl; dr
Instant.ofEpochMilli( 1_317_816_735_000L ) .atZone( ZoneId.of( "Pacific/Auckland" ) ) .format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( new Locale( "en" , "NZ" ) ) )
…также…
LocalDateTime.parse( "2011-10-06 03:35:05".replace( " " , "T" ) ) .atZone( ZoneId.of( "Pacific/Auckland" ) )
java.time
Вопрос и большинство ответов используют устаревшие устаревшие классы даты и времени из самых ранних версий Java. Эти старые классы оказались хлопотными и запутанными. Избежать их. Вместо этого используйте классы java.time.
ISO 8601
Ваша входная строка почти в стандартном формате ISO 8601. Просто замените ПРОБЕЛ посередине на
T
.String input = "2011-10-06 03:35:05".replace( " " , "T" );
LocalDateTime
Теперь выполните синтаксический анализ как a,
LocalDateTime
потому что во входных данных отсутствует информация о смещении от UTC или часовом поясе. ALocalDateTime
не имеет понятия смещения или часового пояса, поэтому он не представляет фактический момент на временной шкале.ZoneOffset
Похоже, вы говорите, что из бизнес-контекста вы знаете, что цель этой строки - представить момент, который на 13 часов опережает UTC. Итак, мы создаем экземпляр
ZoneOffset
.ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe.
OffsetDateTime
Примените его, чтобы получить
OffsetDateTime
объект. Это становится актуальным моментом на временной шкале.ZoneId
Но затем вы упомянули Новую Зеландию. Итак, вы имели в виду конкретный часовой пояс. Часовой пояс - это смещение от UTC плюс набор правил для обработки аномалий, таких как переход на летнее время (DST). Таким образом , мы можем указать
ZoneId
к ,ZonedDateTime
а не просто смещение.Укажите правильное имя часового пояса . Никогда не используйте аббревиатуру из 3-4 букв, например
EST
или,IST
поскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны (!). Например,Pacific/Auckland
.ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime
Примените
ZoneId
.Вы можете легко перейти в другую зону в тот же момент на временной шкале.
ZoneId zParis = ZoneId.of( "Europe/Paris" ); ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis ); // Same moment in time, but seen through lens of Paris wall-clock time.
Отсчитывать от эпохи
Я настоятельно рекомендую не обрабатывать значения даты и времени как отсчет от эпохи, например миллисекунды с начала 1970 года по Гринвичу. Но если нужно, создайте
Instant
из такого числа.Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L );
Затем при желании назначьте часовой пояс, как показано выше, чтобы отойти от UTC.
ZoneId z = ZoneId.of( "Pacific/Auckland" ); ZonedDateTime zdt = instant.atZone( z );
Ваша ценность
1_317_816_735_000L
:2011-10-05T12:12:15Z
(Среда, 5 октября 2011 г., 12:12:15 GMT)2011-10-06T01:12:15+13:00[Pacific/Auckland]
(Четверг, 6 октября 2011 г., 01:12:15 в Окленде, Новая Зеландия).Генерация строк
Чтобы сгенерировать строку в стандартном формате ISO 8601 , просто вызовите
toString
. Обратите внимание, чтоZonedDateTime
стандартный формат разумно расширяется, добавляя название часового пояса в квадратных скобках.Для других форматов ищите Stack Overflow для
DateTimeFormatter
класса. Уже много раз освещали.Укажите a
FormatStyle
и aLocale
.Locale l = new Locale( "en" , "NZ" ); DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l ); String output = zdt.format( f );
Обратите внимание, что часовой пояс не имеет ничего общего с локалью. Вы можете
Europe/Paris
отображать дату и время на японском языке и культурных нормах илиAsia/Kolkata
дату и время на португальском языке и культурных нормах Бразилии.О java.time
Java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытеснять неприятные старые классы даты и времени , такие как
java.util.Date
,.Calendar
, иjava.text.SimpleDateFormat
.Проект Joda-Time , находящийся сейчас в режиме обслуживания , рекомендует перейти на java.time.
Чтобы узнать больше, см. Oracle Tutorial . И поищите в Stack Overflow множество примеров и объяснений.
Большая часть функциональных возможностей java.time перенесена на Java 6 и 7 в ThreeTen-Backport и дополнительно адаптирована для Android в ThreeTenABP (см. Как использовать… ).
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является испытательной площадкой для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь , такие как
Interval
,YearWeek
,YearQuarter
и многие другие.источник
Решение на самом деле довольно простое (чистая, простая Java):
System.out.println(" NZ Local Time: 2011-10-06 03:35:05"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime localNZ = LocalDateTime.parse("2011-10-06 03:35:05",formatter); ZonedDateTime zonedNZ = ZonedDateTime.of(localNZ,ZoneId.of("+13:00")); LocalDateTime localUTC = zonedNZ.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); System.out.println("UTC Local Time: "+localUTC.format(formatter));
ВЫХОД:
NZ Local Time: 2011-10-06 03:35:05 UTC Local Time: 2011-10-05 14:35:05
источник
Посмотрел, и я не думаю, что в Java есть часовой пояс, который равен GMT + 13. Так что я думаю, вам нужно использовать:
Calendar calendar = Calendar.getInstance(); //OR Calendar.getInstance(TimeZone.getTimeZone("GMT")); calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY)+13); Date d = calendar.getTime();
(Если есть, измените "GMT" на этот часовой пояс и удалите вторую строку кода)
ИЛИ ЖЕ
SimpleDateFormat df = new SimpleDateFormat(); df.setTimeZone(TimeZone.getTimeZone("GMT+13")); System.out.println(df.format(c.getTime()));
Если вы хотите установить определенное время / дату, вы также можете использовать:
calendar.set(Calendar.DATE, 15); calendar.set(Calendar.MONTH, 3); calendar.set(Calendar.YEAR, 2011); calendar.set(Calendar.HOUR_OF_DAY, 13); calendar.set(Calendar.MINUTE, 45); calendar.set(Calendar.SECOND, 00);
источник
Мы можем справиться с этим, используя значение смещения
public static long convertDateTimeZone(long lngDate, String fromTimeZone, String toTimeZone){ TimeZone toTZ = TimeZone.getTimeZone(toTimeZone); Calendar toCal = Calendar.getInstance(toTZ); TimeZone fromTZ = TimeZone.getTimeZone(fromTimeZone); Calendar fromCal = Calendar.getInstance(fromTZ); fromCal.setTimeInMillis(lngDate); toCal.setTimeInMillis(fromCal.getTimeInMillis() + toTZ.getOffset(fromCal.getTimeInMillis()) - TimeZone.getDefault().getOffset(fromCal.getTimeInMillis())); return toCal.getTimeInMillis(); }
Фрагмент тестового кода:
System.out.println(new Date().getTime()) System.out.println(convertDateTimeZone(new Date().getTime(), TimeZone .getDefault().getID(), "EST"));
Выход: 1387353270742 1387335270742
источник
Я пробовал этот код
try{ SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss Z"); Date datetime = new Date(); System.out.println("date "+sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); System.out.println("GMT "+ sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("GMT+13")); System.out.println("GMT+13 "+ sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); System.out.println("utc "+sdf.format(datetime)); Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT")); DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z"); formatter.setTimeZone(TimeZone.getTimeZone("GMT+13")); String newZealandTime = formatter.format(calendar.getTime()); System.out.println("using calendar "+newZealandTime); }catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
и получив этот результат
date 06-10-2011 10:40:05 +0530 GMT 06-10-2011 05:10:05 +0000 // here getting 5:10:05 GMT+13 06-10-2011 06:10:05 +1300 // here getting 6:10:05 utc 06-10-2011 05:10:05 +0000 using calendar 06 Oct 2011 18:10:05 GMT+13:00
источник
Джода-Тайм
Классы java.util.Date/Calendar - беспорядок, и их следует избегать.
Обновление: проект Joda-Time находится в режиме обслуживания. Команда советует перейти на классы java.time.
Вот ваш ответ с использованием библиотеки Joda-Time 2.3. Очень просто.
Как отмечено в примере кода, я предлагаю вам по возможности использовать именованные часовые пояса, чтобы ваша программа могла обрабатывать летнее время (DST) и другие аномалии.
Если вы поместили
T
в середину строки вместо пробела, вы можете пропустить первые две строки кода, имея дело с программой форматирования для синтаксического анализа строки. Конструктор DateTime может принимать строку в формате ISO 8601 .// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so. // import org.joda.time.*; // import org.joda.time.format.*; // Parse string as a date-time in UTC (no time zone offset). DateTimeFormatter formatter = org.joda.time.format.DateTimeFormat.forPattern( "yyyy-MM-dd' 'HH:mm:ss" ); DateTime dateTimeInUTC = formatter.withZoneUTC().parseDateTime( "2011-10-06 03:35:05" ); // Adjust for 13 hour offset from UTC/GMT. DateTimeZone offsetThirteen = DateTimeZone.forOffsetHours( 13 ); DateTime thirteenDateTime = dateTimeInUTC.toDateTime( offsetThirteen ); // Hard-coded offsets should be avoided. Better to use a desired time zone for handling Daylight Saving Time (DST) and other anomalies. // Time Zone list… http://joda-time.sourceforge.net/timezones.html DateTimeZone timeZoneTongatapu = DateTimeZone.forID( "Pacific/Tongatapu" ); DateTime tongatapuDateTime = dateTimeInUTC.toDateTime( timeZoneTongatapu );
Сбросьте эти значения…
System.out.println( "dateTimeInUTC: " + dateTimeInUTC ); System.out.println( "thirteenDateTime: " + thirteenDateTime ); System.out.println( "tongatapuDateTime: " + tongatapuDateTime );
При запуске…
источник
отображать дату и время для всех часовых поясов
import java.util.Calendar; import java.util.TimeZone; import java.text.DateFormat; import java.text.SimpleDateFormat; static final String ISO8601 = "yyyy-MM-dd'T'HH:mm:ssZ"; DateFormat dateFormat = new SimpleDateFormat(ISO8601); Calendar c = Calendar.getInstance(); String formattedTime; for (String availableID : TimeZone.getAvailableIDs()) { dateFormat.setTimeZone(TimeZone.getTimeZone(availableID)); formattedTime = dateFormat.format(c.getTime()); System.out.println(formattedTime + " " + availableID); }
источник
Мы можем получить отметку времени UTC / GMT от заданной даты.
/** * Get the time stamp in GMT/UTC by passing the valid time (dd-MM-yyyy HH:mm:ss) */ public static long getGMTTimeStampFromDate(String datetime) { long timeStamp = 0; Date localTime = new Date(); String format = "dd-MM-yyyy HH:mm:ss"; SimpleDateFormat sdfLocalFormat = new SimpleDateFormat(format); sdfLocalFormat.setTimeZone(TimeZone.getDefault()); try { localTime = (Date) sdfLocalFormat.parse(datetime); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.getDefault()); TimeZone tz = cal.getTimeZone(); cal.setTime(localTime); timeStamp = (localTime.getTime()/1000); Log.d("GMT TimeStamp: ", " Date TimegmtTime: " + datetime + ", GMT TimeStamp : " + localTime.getTime()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return timeStamp; }
Он вернет время в формате UTC на основе прошедшей даты.
Мы можем сделать обратное, например отметку времени UTC, на текущую дату и время (наоборот)
public static String getLocalTimeFromGMT(long gmtTimeStamp) { try{ Calendar calendar = Calendar.getInstance(); TimeZone tz = TimeZone.getDefault(); calendar.setTimeInMillis(gmtTimeStamp * 1000); // calendar.add(Calendar.MILLISECOND, tz.getOffset(calendar.getTimeInMillis())); SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); Date currenTimeZone = (Date) calendar.getTime(); return sdf.format(currenTimeZone); }catch (Exception e) { } return ""; }
Надеюсь, это поможет другим. Благодаря!!
источник
Быстрый способ:
String dateText ="Thu, 02 Jul 2015 21:51:46"; long hours = -5; // time difference between places DateTimeFormatter formatter = DateTimeFormatter.ofPattern(E, dd MMM yyyy HH:mm:ss, Locale.ENGLISH); LocalDateTime date = LocalDateTime.parse(dateText, formatter); date = date.with(date.plusHours(hours)); System.out.println("NEW DATE: "+date);
Вывод
НОВАЯ ДАТА: 2015-07-02T16: 51: 46
источник
Ваш подход работает без каких-либо изменений.
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); // Timestamp for 2011-10-06 03:35:05 GMT calendar.setTime(new Date(1317872105000L)); DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); formatter.setTimeZone(TimeZone.getTimeZone("GMT+13")); // Prints 2011-10-06 16:35:05 GMT+13:00 System.out.println(formatter.format(calendar.getTime()));
источник
public Timestamp convertLocalTimeToServerDatetime(String dt,String timezone){ String clientDnT = dt ;// "2017-06-01 07:20:00"; try{ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = sdf.parse(clientDnT); TimeZone tz = TimeZone.getTimeZone(timezone.trim()); // get time zone of user sdf.setTimeZone(tz); // Convert to servertime zone SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); TimeZone tzInAmerica = TimeZone.getDefault(); sdf1.setTimeZone(tzInAmerica); // assign date to date String serverDate = sdf1.format(date); // Convert to servertime zone to Timestamp Date date2 = sdf.parse(serverDate); Timestamp tsm = new Timestamp(date2.getTime()); return tsm; } catch(Exception e){ System.err.println(e); } return null; }
источник
var _timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
и в javaTimeZone tz = TimeZone.getDefault(); tz.getID()
Чтобы найти продолжительность или временной интервал с двумя разными часовыми поясами
import org.joda.time.{DateTime, Period, PeriodType} val s1 = "2019-06-13T05:50:00-07:00" val s2 = "2019-10-09T11:30:00+09:00" val period = new Period(DateTime.parse(s1), DateTime.parse(s2), PeriodType dayTime()) period.getDays period.getMinutes period.getHours
период вывода = P117DT13H40M
days = 117 minutes = 40 hours = 13
источник
Я хотел бы дать современный ответ.
На самом деле вам не нужно преобразовывать дату и время из строки с одним смещением GMT в строку с другим смещением GMT и в другом формате. Скорее в вашей программе сохраняйте момент (момент времени) как надлежащий объект даты и времени. Только когда вам нужно предоставить строковый вывод, отформатируйте ваш объект в желаемую строку.
java.time
Разбор ввода
DateTimeFormatter formatter = new DateTimeFormatterBuilder() .append(DateTimeFormatter.ISO_LOCAL_DATE) .appendLiteral(' ') .append(DateTimeFormatter.ISO_LOCAL_TIME) .toFormatter(); String dateTimeString = "2011-10-06 03:35:05"; Instant instant = LocalDateTime.parse(dateTimeString, formatter) .atOffset(ZoneOffset.UTC) .toInstant();
Для большинства целей
Instant
это хороший выбор для хранения момента времени. Если вам нужно явно указать, что дата и время взяты из GMT, используйтеOffsetDateTime
вместо этого.Преобразование, форматирование и печать вывода
ZoneId desiredZone = ZoneId.of("Pacific/Auckland"); Locale desiredeLocale = Locale.forLanguageTag("en-NZ"); DateTimeFormatter desiredFormatter = DateTimeFormatter.ofPattern( "dd MMM uuuu HH:mm:ss OOOO", desiredeLocale); ZonedDateTime desiredDateTime = instant.atZone(desiredZone); String result = desiredDateTime.format(desiredFormatter); System.out.println(result);
Это напечатано:
Я указал часовой пояс Pacific / Auckland, а не указанное вами смещение, +13: 00. Я понял, что вам нужно новозеландское время, и Пасифик / Окленд лучше говорят об этом. Часовой пояс также учитывает летнее время (DST), поэтому вам не нужно учитывать это в вашем собственном коде (для большинства целей).
Поскольку
Oct
он на английском языке, рекомендуется указать форматеру явную локаль.GMT
тоже может быть локализован, но я думаю, что он просто печатаетсяGMT
во всех регионах.OOOO
в строке шаблонов формата - это один из способов печати смещения, который может быть лучшей идеей, чем печать аббревиатуры часового пояса, которую вы бы получили,z
поскольку сокращения часовых поясов часто неоднозначны. Если хотитеNZDT
(для летнего времени Новой Зеландии), просто введитеz
вместо этого.Ваши вопросы
Я отвечу на ваши пронумерованные вопросы относительно современных классов в java.time.
Нет, современные классы неизменны. Вам нужно создать объект, который с самого начала имеет желаемую дату и время (это имеет ряд преимуществ, включая безопасность потоков).
atZone
Метод , который я использую в коде возвращаетZonedDateTime
с заданной временной зоной. Другие классы даты и времени имеют аналогичный метод, иногда называемыйatZoneSameInstant
или другими именами.С java.time преобразование в новый часовой пояс и форматирование - это два различных шага, как показано.
Да, преобразовать в нужный часовой пояс, как показано, и отформатировать, как показано.
Это не так, как вы думаете, что хорошо демонстрирует лишь пару (многих) проблем проектирования со старыми классами.
Date
нет часового пояса. Только когда вы его распечатываете, егоtoString
метод захватывает ваш местный часовой пояс и использует его для рендеринга строки. Это верно и дляnew Date()
. Такое поведение смутило многих, многих программистов за последние 25 лет.Calender
есть часовой пояс. Это не меняется, когда вы это делаетеcalendar.setTime(new Date(1317816735000L));
.Ссылка
Учебник Oracle: Date Time, объясняющий, как использовать java.time.
источник