эффективно конвертировать DateTime в длинный формат (yyyyMMddHHmmss) в другую зону для сравнения

У меня есть длинное значение, которое представляет дату-время, подобное этому 20200319234500 (переводится на 19 марта 2020 года, 23:45:00 PM). Я хочу, чтобы это длинное значение (20200319234500) снова преобразовалось в другой часовой пояс в длинном формате, чтобы я мог сделать больше и меньше чем сравнение с текущей датой в местном часовом поясе.

Я хочу делать это эффективно, поэтому мне не нужно создавать какие-либо объекты во время выполнения или создавать строки после запуска. но похоже, что сначала я должен преобразовать долгое время в строку, а затем вызвать функцию ZonedDateTime.parse (), чтобы получить дату и время, а затем провести сравнение. Есть ли другой способ сделать это?

 //This is known at compile time
        ZoneId baseZone = ZoneId.of("Europe/Paris");
        //This is known at compile time
        ZoneId localZone = ZoneId.of("America/New_York");
        //This is known at compile time
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss").withZone(baseZone);

        long baseDateTime = 20210321234500L;

        //Dont want o be doing string operations. Is there a way to keep it in long and get another long in a different zone?
        ZonedDateTime convertedBaseDateTime  = ZonedDateTime.parse(Long.toString(baseDateTime), formatter);
        //Can I just get a long that represents current time in local zone? local zone is not JVM zone
        ZonedDateTime localDateTime = ZonedDateTime.now(localZone);
        //Thats the only operation I want to perform
        boolean result = convertedBaseDateTime.isBefore(  localDateTime);

person bsobaid    schedule 21.09.2020    source источник
comment
Я думаю, что если я смогу получить смещение между двумя часовыми поясами в формате int / long, я могу просто добавить его в свой baseDateTime. Но как мне получить смещение long / int между зонами? Кроме того, как получить текущее время в локальной зоне для сравнения?   -  person bsobaid    schedule 21.09.2020
comment
Не создавать новые строки - странное требование. Вы уверены, что создание новых строк вызовет проблемы с производительностью?   -  person Sweeper    schedule 21.09.2020
comment
ИМХО, это уже самый эффективный способ. Любой другой способ просто сделает код более сложным (и, вероятно, без какого-либо повышения производительности).   -  person Arvind Kumar Avinash    schedule 21.09.2020
comment
Вам не нужно преобразовывать промежуточные зоны. ZonedDateTime.isBefore() принимает во внимание, находится ли другой ZonedDateTime в другом часовом поясе (возможно, преобразование выполняется за кулисами, но вы можете оставить это как есть).   -  person Ole V.V.    schedule 21.09.2020


Ответы (2)


Вы можете выполнить математику, чтобы определить год, месяц, день, час. минута, секунда из длинного, а затем вы можете передать это ZonedDateTime.of

long baseDateTime = 20210321234500L;
int year = (int)(baseDateTime / 10000000000L);
int month = (int)(baseDateTime / 100000000L % 100);
int day = (int)(baseDateTime / 1000000L % 100);
int hour = (int)(baseDateTime / 10000L % 100);
int minute = (int)(baseDateTime / 100L % 100);
int second = (int)(baseDateTime % 100);
ZonedDateTime convertedBaseDateTime = ZonedDateTime.of(year, month, day, hour, minute, second, 0, baseZone);

Это не создаст новых строк.

После этого обратите внимание на то, что если вы просто хотите проверить, раньше ли время даты, вам не нужна зона на данный момент. Вам просто нужно сравнить количество (милли / нано) секунд с эпохи тогда и сейчас.

// don't need these
// ZoneId localZone = ZoneId.of("America/New_York");
// ZonedDateTime localDateTime = ZonedDateTime.now(localZone);

// you just need to compare
convertedBaseDateTime.toEpochSecond() * 1000 < System.currentTimeMillis()

Тем не менее, если для вас так важна производительность, возможно, вам не следует использовать Java, а вместо этого следует использовать более низкоуровневый язык.

person Sweeper    schedule 21.09.2020
comment
Java должна быть достаточно производительной. Если метод запускается часто, он будет скомпилирован в собственный код точно так же, как, скажем, код C с самого начала. Если вам нужно быть уверенным, вам, конечно же, нужно провести свои замеры. - person Ole V.V.; 21.09.2020

long baseDateTime = 20210321234500L; LocalDateTime time = LocalDateTime.ofEpochSecond (baseDateTime /1000,0,ZoneOffset.ofHours(8)); // тогда вы можете использовать time2.isAfter () или какой-либо другой метод для сравнения, то есть ссылку на jdk 8 API.

person Allen    schedule 21.09.2020
comment
Это число представляет собой строковое представление года, месяца и так далее, а не эпохи Unix. - person chrylis -cautiouslyoptimistic-; 21.09.2020