java.time
Я предлагаю следующие реализации ваших двух методов.
public static long getStartTimeOfWeek() {
WeekFields wf = WeekFields.of(Locale.getDefault());
return LocalDate.now(ZoneOffset.UTC)
.with(wf.dayOfWeek(), 1)
.atStartOfDay(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
}
public static long getMonthDateFirstdate(){
return YearMonth.now(ZoneOffset.UTC)
.atDay(1)
.atStartOfDay(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
}
Чтобы попробовать их:
System.out.println(Instant.ofEpochMilli(getStartTimeOfWeek()));
System.out.println(Instant.ofEpochMilli(getMonthDateFirstdate()));
Когда я только что запустил эти две строки на своем компьютере, я получил:
2019-03-18T00:00:00Z
2019-03-01T00:00:00Z
Поскольку в вашем ожидаемом и наблюдаемом выходных данных упоминается UTC, я предположил, что вам нужны операции в UTC. И поскольку понедельник - первый день недели в моем регионе, я получил понедельник 18 марта в первой строке.
Я предлагаю вам избежать класса Calendar
. Этот класс плохо спроектирован и давно устарел и, следовательно, плохой инструмент для не совсем тривиальных операций с датой и временем, подобных вашей. Вместо этого я использую java.time, современный Java-интерфейс даты и времени. У него гораздо лучшая поддержка того, что вы делаете, и с ним гораздо приятнее работать.
Что пошло не так в вашем коде?
Нам не совсем понятно, почему вы получили результаты, которые вы получили, поскольку вы не предоставили полный пример, а поведение вашего кода зависит от часового пояса и локали. Потенциальные проблемы включают в себя:
- Вероятное объяснение, почему вы получили
18:30:00 UTC 6:30 pm
, состоит в том, что вы запускали свой код в часовом поясе со смещением UTC +05: 30, например, Азия / Калькутта или Азия / Коломбо. Вы получили начало дня в этом часовом поясе. Это тот же момент времени, что и в 18:30 предыдущего дня в UTC.
12:47:15 UTC 12:47 pm
выглядит странно. Это может происходить из-за того, что ваша константа ONE_DAY
имеет неправильное значение.
cal.set(Calendar.DAY_OF_WEEK, 1);
устанавливает день недели равным 1 = воскресенье (если я правильно помню эти константы, я никогда не уверен), но в некоторых местах будет выбрано предыдущее воскресенье, в других местах - в следующее воскресенье, и в в других местах он будет меняться в зависимости от дня недели.
- Кажется, что в
getMonthDateFirstdate
вы забыли установить час дня. Легко забыть с классом Calendar
, где вы должны устанавливать каждое поле индивидуально (приятно, что вы вспомнили миллисекунды, многие их забывают).
- Использовать полуоткрытый интервал. Вместо того, чтобы желать, чтобы конец был
Sun, 31 Mar 2019 23:59:59 UTC 11:59 pm
, рекомендуется установить его на Mon, 01 Apr 2019 00:00:00 UTC 12:00 am
и использовать его в качестве открытой конечной точки, то есть ваш интервал от времени начала включительно до вашего времени окончания эксклюзивный . Таким образом, это означает, что момент времени находится в пределах интервала, только если он строго до времени окончания.
Вопрос: Могу ли я использовать java.time на уровне API Android 20?
Да, java.time
прекрасно работает на старых и новых устройствах Android. Для этого требуется как минимум Java 6 .
- В Java 8 и более поздних версиях и на новых устройствах Android (от 26 уровня API, как мне сказали) новый API поставляется встроенным.
- В Java 6 и 7 получают ThreeTen Backport, бэкпорт новых классов (ThreeTen для JSR 310, где впервые был описан современный API).
- На (более старом) Android используйте Android-версию ThreeTen Backport. Это называется ThreeTenABP. Убедитесь, что вы импортировали классы даты и времени из пакета
org.threeten.bp
и подпакетов.
Ссылки