преобразовать дату в эпохальные секунды в Java с учетом местного часового пояса - PullRequest
0 голосов
/ 08 ноября 2019

Я хотел бы преобразовать диапазон дат в эпоху (12 часов утра этого дня, 23.59 часов вечера GMT этого дня).

  1. fromDate = 2019-10-25T00: 00: 00-07:00, toDate = 2019-10-25T23: 59: 59-07: 00: хотел бы вернуться (1571986800,1572073199) (эквивалентно метке времени по Гринвичу 25 октября 2019 года, 7:00:00 AM, по Гринвичу 26 октября,2019 6:59:59 AM)
  2. fromDate = 2019-10-24T00: 00: 00-07: 00, toDate = 2019-10-24T23: 59: 59-07: 00: хотел бы вернуться(1571900400,1571986799) (эквивалентно метке времени GMT 24 октября 2019 г. 7:00:00 AM, GMT 25 октября 2019 г. 6:59:59 AM)

Моя попытка:

fromDate = String.valueOf(formatter.parse(fromDate.substring(0, 19)).toInstant().getEpochSecond());
toDate = String.valueOf(formatter.parse(toDate.substring(0, 19)).toInstant().getEpochSecond());
epochDateRange.append("(").append(fromDate).append(",").append(toDate).append(")");

При отладке с настройкой на другой часовой пояс: т.е. добавить следующий параметр в eclipse - отладочная конфигурация

'-Duser.timezone=Asia/Kuala_Lumpur'
  1. Для указанного часового пояса 25 октября возвращается (1571932800, 1572019199), но желаемый результат равен (1571986800,1572073199)

  2. Для указанного часового пояса 24 октября он возвращает (1571846400,1571932799), но желаемый результат равен (1571900400,15719867)99)

Любая помощь будет оценена. Спасибо.

Ответы [ 2 ]

2 голосов
/ 08 ноября 2019

Ваш вопрос довольно запутанный. Так что я могу только догадываться о том, что вы пытаетесь сделать. Но главная проблема может заключаться в том, что вы неправильно понимаете, что такое отсчет времени.

Во-первых, обычно используется десятки эталонных эпох даты и времени. Всегда указывайте, кого вы имеете в виду. Классы даты и времени в комплекте с Java используют первый момент 1970 года в UTC, 1970-01-01T00: 00Z.

Во-вторых, вы можете не осознавать, как отсчет времени должен ссылаться на смещение или часовой пояс, чтобы иметь какой-либо смысл. Опять же, в Java мы используем UTC, как упомянуто выше, и, как видно из Z в конце приведенной выше строки, в стандартном формате ISO 8601 .

Другая проблема заключается в том, что вы, кажется, пытаетесь представить начало и конец всего дня, прибивая последний момент дня. Это проблематично. В обработке даты и времени мы обычно используем полуоткрытый подход к определению промежутка времени. В полуоткрытом начале - включительно , а окончание - эксклюзив . Таким образом, день начинается в его первый момент и продолжается, но не включает первый момент следующего дня.

OffsetDateTime start = OffsetDateTime.parse( "2019-10-25T00:00:00-07:00" );
OffsetDateTime stop = start.plusDays( 1 ) ;

start.toString (): 2019-10-25T00:00-07: 00

stop.toString (): 2019-10-26T00: 00-07: 00

Другая проблема связана с использованием 12:00:00 AM. Это может быть хитрый способ представить перекат в полночь. Я предлагаю придерживаться 24-х часов для вашего кодирования. Таким образом, день в UTC всегда начинается с 00:00:00:00. (Кстати, день не всегда начинается в 00:00 в некоторых часовых поясах в некоторые даты.)

Еще одна проблема заключается в использовании смещений, а не часовых поясов. Если вы знаете, что часовой пояс, например, America/Phoenix, используйте его, а не смещение -07:00.

Что касается вашего прыжка со смещения -07: 00 по Гринвичу, вы меня там потеряли. Понятия не имею, что вы имеете в виду. Но, возможно, это поможет.

Если вы хотите узнать, что такое 2019-10-25T00: 00: 00-07: 00 в UTC, просто извлеките Instant из вашего OffsetDateTime. Instant всегда в UTC, по определению.

OffsetDateTime
.parse( "2019-10-25T00:00:00-07:00" )
.toInstant()
.toString() 

2019-10-25T07: 00: 00Z

Итак, ваш звонок 2019-10-25T00: 00: 00-07: 00, что эквивалентно 25 октября 2019 года 12:00:00 по Гринвичу (по Гринвичу и по Гринвичу, фактически, то же самое) практически бессмысленно-07:00 в первой строке означает, что дата-время отстает на семь часов по UTC. Таким образом, одна и та же дата с тем же временем суток в UTC, возможно, не может представлять один и тот же момент.

Возможно, вашей целью является получение первого момента дня, который видят жители какого-то региона, часового пояса.

ZoneId z = ZoneId.of( "Asia/Kuala_Lumpur" ) ;
LocalDate ld = LocalDate.parse( "2019-10-25" ) ;
ZonedDateTime zdtStart = ld.atStartOfDay( z ) ;
ZonedDateTime zdtStop = zdtStart.plusDays( 1 ) ;

Обратите внимание на запуск и останов при настройке на UTC.

Instant utcStart = zdtStart.toInstant() ;
Instant utcStop = zdtStop.toInstant() ;

Получите отсчет с эпохи 1970-01-01T00: 00: 00Z с детализацией целых секунд.

long secondsSinceEpochStart = utcStart.getEpochSecond() ;
long secondsSinceEpochStop = utcStop.getEpochSecond() ;

zdtStart / zdtStop: 2019-10-25T00: 00 + 08: 00 [Asia / Kuala_Lumpur] / 2019-10-26T00: 00 + 08: 00 [Asia / Kuala_Lumpur]

utcStart / utcStop: 2019-10-24T16: 00: 00Z / 2019-10-25T16: 00: 00Z

секундSinceEpochStart / секундSinceEpochStop: 1571932800/1572019200

Смотрите весь этот код, запущенный в режиме реального времени на IdeOne.com . Вы можете легко пробовать и экспериментировать там.

Кстати, если вы проделываете большую работу, отслеживая отрезки времени, добавьте библиотеку ThreeTen-Extra вВаш проект для доступа к классу Interval. Этот класс представляет пару объектов Instant, а также множество полезных методов, таких как abuts, contains и т. Д.

ZonedDateTime start = LocalDate.of( 2019, Month.OCTOBER , 25 ).atStartOfDay( ZoneOffset.UTC ) ;
Interval dayInUtc = Interval.of( 
    start.toInstant() ,
    start.plusDays( 1 ).toInstant() 
) ;
String epochCounts = dayInUtc.getStart().getEpochSecond() + "/" + dayInUtc.getEnd().getEpochSecond() ;

… и в часовом поясе:

ZonedDateTime start = LocalDate.of( 2019, Month.OCTOBER , 25 ).atStartOfDay( ZoneId.of( "Asia/Kuala_Lumpur" ) ) ;
Interval dayInKualaLumpur = Interval.of( 
    start.toInstant() ,
    start.plusDays( 1 ).toInstant() 
) ;
String epochCounts = dayInKualaLumpur.getStart().getEpochSecond() + "/" + dayInKualaLumpur.getEnd().getEpochSecond() ;
0 голосов
/ 09 ноября 2019

Поскольку ваши строки содержат смещение UTC, вам необходимо проанализировать это смещение, чтобы получить правильное время.

    String fromDateString = "2019-10-25T00:00:00-07:00";
    long fromEpochSecond = OffsetDateTime.parse(fromDateString).toEpochSecond();
    System.out.println("fromEpochSecond: " + fromEpochSecond);

Выходные данные этого фрагмента:

fromEpochSecond: 1571986800

Это метка времени Unix (количество секунд с начала эпохи), которую вы запросили. Сделайте то же самое с другими строками (вы захотите заключить преобразование в служебный метод).

Обратите внимание, что этот код не зависит от часового пояса. Он просто доверяет смещению в строке.

Несколько дополнительных советов:

  • Я подозреваю, что ваш код использует старый класс DateFormat и / или SimpleDateFormat,Не делай этого. Эти классы общеизвестно хлопотны и давно устарели. Если вам нужен форматтер, используйте современный DateTimeFormatter из java.time.
  • Используйте полуоткрытые интервалы. Не представляйте конец дня как 23:59:59. Представляет конец дня по первому моменту следующего дня исключая . Поэтому 25 октября обычно заканчивается в 26 октября 00:00:00 и всегда в первый момент 26 октября.
  • Если у вас есть дата и часовой пояс, найдите метку времени Unix дляначало дня примерно так:

        ZoneId zone = ZoneId.of("Asia/Kuala_Lumpur");
        LocalDate date = LocalDate.of(2019, Month.OCTOBER, 25);
        long startOfDayEpochSecond = date.atStartOfDay(zone).toEpochSecond();
        System.out.println("startOfDayEpochSecond: " + startOfDayEpochSecond);
    

    startOfDayEpochSecond: 1571932800

    Это не то же время, что и выше, потому что Куала-Лумпур не по смещению -07: 00. Я считаю, что это в +08: 00.

...