Rrule До значения тега данных
Я работаю над проектом, который использует правила для генерации следующих вхождений. Но я не могу понять, что мне нужно поместить в тег UNTIL из правила.
String str="RRULE:FREQ=MONTHLY;UNTIL=20190625T000000Z;INTERVAL=2;";
ИДК, как конвертировать дату в "20190625T000000Z"
.Я использую Java-библиотеку rfc 2445. Если пользователь вводит дату в виде строки, например:25/06/2019......
Мне нужно установить это значение в теге UNTIL, как показано выше. Если я установлю значение по умолчанию в UNTIL, тогда оно будет работать, но не тогда, когда я сделаю его удобным для пользователя. Я беру все значения от пользователя в качестве даты начала, даты окончания, интервала, дня рождения, до... Но не знаю, какое значение установить до. Если кто-то может помочь.. Заранее спасибо.
1 ответ
Разбор базового формата ISO 8601
Ваш вклад 20190625T000000Z
это "базовый" вариант стандартного формата ISO 8601 для представления момента в формате UTC. Слово "базовый" означает минимизацию использования разделителей (я не рекомендую этого, поскольку это делает строку менее читаемой людьми).
Определение шаблона форматирования для соответствия вводу.
String input = "20190625T000000Z";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMdd'T'HHmmssX" );
OffsetDateTime odt = OffsetDateTime.parse( input , f );
Дамп на консоль.
System.out.println("odt.toString(): " + odt);
Смотрите этот код в прямом эфире на IdeOne.com.
odt.toString (): 2019-06-25T00:00Z
Перевод даты в момент
Если пользователь вводит дату в виде строки, например:25/06/2019...... мне нужно установить это значение в теге UNTIL, как показано выше
Сначала проанализируйте эту входную строку в LocalDate
, представляющий значение только для даты, без времени суток и без часового пояса.
DateTimeFormatter fDateOnly = DateTimeFormatter.ofPattern( "dd/MM/uuuu" );
LocalDate ld = LocalDate.parse( "25/06/2019" , fDateOnly );
ld.toString (): 2019-06-25
Что касается перевода этой даты в момент (дата с указанием времени дня в зоне или смещением от UTC), это сложнее, чем кажется на первый взгляд.
Такая дата, как 25 июня 2019 года, представляет собой целый день. И теоретическая дата в этом. Моменты, когда день начинается и заканчивается, различаются по всему земному шару в зависимости от часового пояса. Новый день начинается гораздо раньше в Токио, Япония, чем в Париже, Франция, и даже позже, в Монреале, Квебеке.
Другая проблема заключается в том, что день не всегда начинается в 00:00:00. Из-за таких аномалий, как летнее время (DST), первый момент дня в некоторые даты в некоторых зонах может быть примерно 01:00:00. Пусть классы java.time определяют первый момент.
ZoneId z = ZoneId.of( "Africa/Tunis" );
ZonedDateTime zdt = ld.atStartOfDay( z );
zdt.toString (): 2019-06-25T00:00 + 01: 00 [Африка / Тунис]
Тот ZonedDateTime
объект представляет определенный момент. Но он использует настенные часы, принятые людьми определенного региона (часового пояса). Ваша цель - момент в UTC. К счастью, мы можем отрегулировать из зоны в UTC, преобразовав в OffsetDateTime
(дата и время с контекстом смещения от UTC, а не с часовым поясом). Мы можем указать UTC (смещение нуля) по ZoneOffset.UTC
постоянная.
OffsetDateTime odt = zdt.toOffsetDateTime().withOffsetSameInstant( ZoneOffset.UTC );
odt.toString (): 2019-06-24T23: 00Z
Обратите внимание, что 00:00 25-го в Тунисе 11 вечера "вчера" 24-го в UTC. Тот же самый момент, та же самая одновременная точка на временной шкале, но два разных времени настенных часов.
Наконец, нам нужна строка в этом "базовом" формате ISO 8601. Используйте тот же форматер, который мы определили выше.
DateTimeFormatter fIso8601DateTimeBasic = DateTimeFormatter.ofPattern( "uuuuMMdd'T'HHmmssX" );
String output = odt.format( fIso8601DateTimeBasic );
выход: 20190624T230000Z
Смотрите этот код в прямом эфире на IdeOne.com.
В чем разница между часовым поясом и смещением от UTC? Смещение - это просто количество часов, минут и секунд. Не больше, не меньше, просто число (ну, три цифры). Часовой пояс гораздо больше. Часовой пояс - это история прошлых, настоящих и будущих изменений в смещении, используемом людьми определенного региона. Например, в большей части Северной Америки смещение меняется два раза в год, начиная с часа вперед, а затем с уменьшением на час (безумие летнего времени (DST)).
Совет: обработка даты и времени на удивление хитрая и скользкая. Если вы работаете с календарями и спецификацией iCalendar для обмена данными, я предлагаю вам немало времени изучить концепции и практику с ведущими в отрасли классами java.time.
О java.time
Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые классы даты и времени, такие как java.util.Date
, Calendar
& SimpleDateFormat
,
Чтобы узнать больше, смотрите Oracle Tutorial. И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310.
Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.
Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*
классы.
Где взять классы java.time?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11 и более поздние версии - часть стандартного API Java со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и Java SE 7
- Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport.
- Android
- Более поздние версии Android связывают реализации классов java.time.
- Для более ранних версий Android (<26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP….
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval
, YearWeek
, YearQuarter
и многое другое.