Я пытаюсь вычислить время, добавляя минуты к заданной дате и времени. Это хорошо работает с другим временем, но не для летнего времени [восточное время Канады].
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 из-за летнего времени.
Я хочу, чтобы он игнорировал настройки летнего времени. Я попробовал использовать часовой пояс, местную дату и время, но это не сработало должным образом. Любая помощь будет оценена по достоинству.
Я хочу, чтобы он игнорировал настройки летнего времени. Я пробовал использовать часовой пояс, местную дату-... Тогда ваши расчеты будут неправильными, какой бы API вы ни использовали. Но так получилось, что вам следует использовать java.time
Прекратите использовать эти ужасные устаревшие классы даты и времени. Используйте только классы java.time. Реализация включена в Android 26+. Для более ранних версий Android новейшие инструменты обеспечивают большую часть функций java.time посредством «десахаризации API».
Нет, вы действительно не хотите игнорировать летнее время (DST). В день перехода на летнее время «Впереди весна» вы обманете своих пользователей на один час меньше, если не учтете летнее время. Более того, желаемое время приземления в переходный час не существует в этот день в этой зоне, поэтому вы используете бессмысленное значение.
Вы написали (в своем вопросе):
Я попробовал использовать часовой пояс, местную дату и время, но это не сработало должным образом.
Я не знаю, имеете ли вы в виду класс 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
не влияют настройки летнего времени.
Обратитесь к этому уроку.
Абра прав, и я тоже ;)
Это сработало. То, как я добавлял минуты с помощью LocalDateTime, кажется неправильным. Спасибо большое, помогло!
Instant.now().plus( Duration.ofMinutes( 225 ) )
Ответ Абры является точным ответом на ваш прямой вопрос об игнорировании часового пояса.
К сожалению, ваш вопрос ошибочен. Вы моделируете истечение срока действия. Поэтому игнорировать временные аномалии, такие как Летнее время (DST), при работе с датой/временем конкретной местности, невозможно.
В вашем примере вы попытаетесь представить несуществующее время суток, приземлившись в час, пропущенный во время переключения «Spring впереди» на летнее время. И ваш подход в конечном итоге приведет к тому, что вы обманете своих пользователей на час во время перехода на летнее время «Spring вперед» и предоставите дополнительный час во время перехода на летнее время «Откат».
Реальное решение — не использовать часовой пояс и не использовать дату/время населенного пункта. Вместо этого используйте время UTC.
UTC — временной меридиан. Вы можете представить себе, что этот меридиан UTC находится в Королевской обсерватории в Гринвиче, где полдень наступает, когда солнце находится прямо над головой. Полдень в местах восточнее наступает на определенное количество часов-минут-секунд раньше, а полдень в местах западнее наступает на определенное количество часов-минут-секунд позже.
Эти часы-минуты-секунды называются смещением от UTC. Например, люди в районе Парижа, Франция, прямо сейчас установили свои часы на два часа вперед от UTC.
Политики в каждом регионе время от времени решают изменить смещение, которое будут соблюдать люди, находящиеся под их юрисдикцией. Летнее время, но это одна из многих причин, по которым они могут так решить. Внутренняя политика, дипломатия, война и оккупация – вот еще несколько причин.
История этих изменений в прошлом, настоящем и будущем представляет собой часовой пояс. Часовой пояс обозначается в формате Continent/Region
, например Europe/Paris
.
Дело в том, что политическое время через часовые пояса всегда находится под угрозой изменения. Напротив, время 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 ) ;
Если вы не используете версию Java до Java 8, вам следует использовать API даты и времени .