Как я могу заставить свой календарь игнорировать корректировки летнего времени?

Я пытаюсь вычислить время, добавляя минуты к заданной дате и времени. Это хорошо работает с другим временем, но не для летнего времени [восточное время Канады].

 public static GregorianCalendar addMinuts(GregorianCalendar newDate, int minutes) {
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(newDate.getTime());

        Log.i("UtilApp", "expiry date before add minutes " + cal.getTime());
        cal.add(Calendar.MINUTE, minutes);
        Log.i("UtilApp", "expiry date after add " + minutes + " minutes " + cal.getTime());
        return setGreCalendar(cal.getTime());
    }

 public static GregorianCalendar setGreCalendar(Date date) {
        Date date1;
        GregorianCalendar gregorianCalendar = new GregorianCalendar();
        if (date != null) {
            date1 = date;
            gregorianCalendar.setTime(date1);
        }
        return gregorianCalendar;
    }

Например: - Я добавил 225 минут, что составляет 3 часа 45 минут, к 9 марта, и это дает точную дату и время, поскольку летнее время не действует.

9 марта

А 10 марта действует летнее время, поэтому вместо 03:45 я получаю 04:45 с теми же 225 минутами. Календарь пропускает время между 2:00 и 3:00 из-за летнего времени.

10 марта

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

Если вы не используете версию Java до Java 8, вам следует использовать API даты и времени .

Abra 30.05.2024 08:07

Я хочу, чтобы он игнорировал настройки летнего времени. Я пробовал использовать часовой пояс, местную дату-... Тогда ваши расчеты будут неправильными, какой бы API вы ни использовали. Но так получилось, что вам следует использовать java.time

g00se 30.05.2024 09:06

Прекратите использовать эти ужасные устаревшие классы даты и времени. Используйте только классы java.time. Реализация включена в Android 26+. Для более ранних версий Android новейшие инструменты обеспечивают большую часть функций java.time посредством «десахаризации API».

Basil Bourque 30.05.2024 16:08

Нет, вы действительно не хотите игнорировать летнее время (DST). В день перехода на летнее время «Впереди весна» вы обманете своих пользователей на один час меньше, если не учтете летнее время. Более того, желаемое время приземления в переходный час не существует в этот день в этой зоне, поэтому вы используете бессмысленное значение.

Basil Bourque 30.05.2024 16:12
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы написали (в своем вопросе):

Я попробовал использовать часовой пояс, местную дату и время, но это не сработало должным образом.

Я не знаю, имеете ли вы в виду класс LocalDateTime, потому что если да, то он должен работать так, как вы ожидаете, поскольку класс LocalDateTime не имеет часового пояса, тогда как класс Calendar делает то, что наследует его подкласс GregorianCalendar.

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

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class AdMinute {

    public static void main(String[] args) {
        LocalDate ld = LocalDate.of(2024, 3, 10);
        LocalDateTime ldt = ld.atStartOfDay();
        System.out.println("Org: " + ldt);
        System.out.println("Add: " + ldt.plus(225, ChronoUnit.MINUTES));
    }
}

Вот результат выполнения приведенного выше кода:

Org: 2024-03-10T00:00
Add: 2024-03-10T03:45

Обратите внимание, что я нахожусь в Израиле, и летнее время началось 29 марта. В 2 часа ночи часы были переведены на 3 часа ночи. Если я заменю дату в приведенном выше коде на 29 (а не на 10), я все равно получу тот же результат. Следовательно, на использование LocalDateTime не влияют настройки летнего времени.

Обратитесь к этому уроку.

Абра прав, и я тоже ;)

g00se 30.05.2024 09:23

Это сработало. То, как я добавлял минуты с помощью LocalDateTime, кажется неправильным. Спасибо большое, помогло!

DigitV23 31.05.2024 15:19

вр; доктор

Instant.now().plus( Duration.ofMinutes( 225 ) )

Игнорировать летнее время ошибочно

Ответ Абры является точным ответом на ваш прямой вопрос об игнорировании часового пояса.

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

В вашем примере вы попытаетесь представить несуществующее время суток, приземлившись в час, пропущенный во время переключения «Spring впереди» на летнее время. И ваш подход в конечном итоге приведет к тому, что вы обманете своих пользователей на час во время перехода на летнее время «Spring вперед» и предоставите дополнительный час во время перехода на летнее время «Откат».

время UTC

Реальное решение — не использовать часовой пояс и не использовать дату/время населенного пункта. Вместо этого используйте время UTC.

Временной меридиан

UTC — временной меридиан. Вы можете представить себе, что этот меридиан UTC находится в Королевской обсерватории в Гринвиче, где полдень наступает, когда солнце находится прямо над головой. Полдень в местах восточнее наступает на определенное количество часов-минут-секунд раньше, а полдень в местах западнее наступает на определенное количество часов-минут-секунд позже.

Смещение от UTC

Эти часы-минуты-секунды называются смещением от UTC. Например, люди в районе Парижа, Франция, прямо сейчас установили свои часы на два часа вперед от UTC.

Политическое время

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

Часовой пояс

История этих изменений в прошлом, настоящем и будущем представляет собой часовой пояс. Часовой пояс обозначается в формате Continent/Region, например Europe/Paris.

Время UTC стабильно

Дело в том, что политическое время через часовые пояса всегда находится под угрозой изменения. Напротив, время UTC, время, отслеживаемое с нулевым смещением, стабильно и неизменно.

Поэтому программисты и системные администраторы должны думать о времени UTC (смещение нуля) как об одном истинном времени. Все остальные — лишь вариации. За некоторыми исключениями, часы на ваших серверах должны быть установлены в формате UTC, ведение журналов должно вестись в формате UTC, а хранение и обмен данными — в формате UTC.

Избегайте устаревших классов даты и времени

Еще один важный момент: вы используете ужасно ошибочные классы даты и времени, которые много лет назад были полностью вытеснены современными классами java.time, определенными в JSR 310. Никогда не используйте их. Используйте только классы java.time.

Пример кода

Duration

Если вы хотите установить срок действия 225 минут, используйте класс Duration, чтобы представить этот промежуток времени, не привязанный к временной шкале.

Duration duration = Duration.ofMinutes( 225 ) ;

Instant

Если вы имеете в виду 225 минут спустя, определите текущий момент в формате UTC. Для этого используйте класс Instant. Объект Instant представляет момент, конкретную точку на временной шкале, видимую со смещением, равным нулю.

Instant now = Instant.now() ;

Добавьте продолжительность, чтобы определить срок действия.

Instant expiry = now.plus( duration ) ;

Теперь у вас есть срок действия, невосприимчивый к прихотям политиков.

Этот Instant объект в вашем случае должен использоваться для хранения данных, обмена данными и бизнес-логики.

ZonedDateTime

Когда придет время отобразить это значение пользователю, настройте его на желаемый/ожидаемый часовой пояс.

ZoneId zoneId = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = expiry.atZone( zoneId ) ;

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

Не храните и не обменивайте этот ZonedDateTime предмет. В вашем случае вам следует использовать Instant для большинства целей, кроме презентации пользователю, как указано выше.

DateTimeFormatter

Создать текст, локализованный для пользователя.

Locale locale = Locale.CANADA_FRENCH ; 
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale) ;
String output = zdt.format( formatter ) ;

Другие вопросы по теме