Получить отметку времени для начала дня
Я храню время/даты в базе данных, используя временную метку unix. Затем я хочу получить все экземпляры в определенный день, поэтому мне нужно вычислить временную метку для начала дня, чтобы запросить базу данных.
Я сделал аналогичную вещь в php, передав mktime значения для дня/месяца/года из объекта даты и установив час и минуту на ноль. Кажется, что в java/android не работают аналогичные функции (функции для получения определенных частей даты устарели)
Может ли кто-нибудь дать некоторые рекомендации по этому поводу? благодаря
Редактировать:
Хорошо, поэтому я понял, что это может сработать:
public static int startOfDay(Timestamp time) {
Calendar cal = dateToCalendar(new Date(time.getTime()));
cal.add(Calendar.HOUR_OF_DAY, -Calendar.HOUR_OF_DAY);
cal.add(Calendar.MINUTE, -Calendar.MINUTE);
cal.add(Calendar.SECOND, -Calendar.SECOND);
Log.i("Time", cal.getTime().toString());
return (int) cal.getTimeInMillis()/1000;
}
Однако когда я запустил это сейчас, я получил:
Сб Дек 15 01:24:00 GMT 2012
Секунды правильные, но час и минута неправильны?
Ответы
Ответ 1
При работе со временем вы всегда должны учитывать часовые пояса. Временные метки базы данных всегда должны храниться в одном часовом поясе (например, в формате UTC). Затем ваши вычисления должны учитывать, что пользователи могут находиться в разных часовых поясах и что они могут изменять часовые пояса.
Если вы хотите вычислить начало дня в часовом поясе, который пользователь установил в своем телефоне. Создайте экземпляр Calendar
с помощью:
Calendar cal = Calendar.getInstance();
Чтобы получить экземпляр для определенного часового пояса, используйте:
// use UTC time zone
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Затем установите начало дня:
cal.setTime(time); // compute start of the day for the timestamp
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Ответ 2
public static int startOfDay(Timestamp time) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(time.getTime());
cal.set(Calendar.HOUR_OF_DAY, 0); //set hours to zero
cal.set(Calendar.MINUTE, 0); // set minutes to zero
cal.set(Calendar.SECOND, 0); //set seconds to zero
Log.i("Time", cal.getTime().toString());
return (int) cal.getTimeInMillis()/1000;
}
Ответ 3
ТЛ; др
ZoneId z = ZoneId.of( "America/Montreal" );
long secondsSinceEpoch = ZonedDateTime.now( z ).toLocalDate().asStartOfDay( z ).toEpochSecond() ;
Детали
Принятый ответ Томика правильный, но устаревший. Классы java.time вытеснили старые классы устаревших дат.
Как сказано в этом ответе, вы должны учитывать часовой пояс, когда начинаете день. Часовой пояс имеет решающее значение для определения даты. В любой данный момент дата изменяется по всему миру по зонам. Например, через несколько минут после полуночи в Париже Франция - новый день, еще "вчера" в Монреале Квебек.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( z );
Получение первого момента дня требует прохождения через LocalDate
. Класс LocalDate
представляет значение даты только без времени и без часового пояса.
LocalDate today = zdt.toLocalDate();
ZonedDateTime zdtTodayStart = today.atStartOfDay( z );
Обратите внимание, что мы разрешаем java.time определять начало дня, а не предполагать и жестко кодировать 00:00:00
. Из-за летнего времени (DST) и других аномалий день может начинаться в другое время, например, 01:00:00
.
По-видимому, по unix timestamp
вы имеете в виду подсчет целых секунд с первого момента 1970 года в UTC. Класс ZonedDateTime
имеет способ предоставить вам это число. Обратите внимание, что это может означать потерю данных, поскольку ZonedDateTime
может иметь долю секунды с разрешением наносекунд.
long secondsSinceEpoch = zdtTodayStart.toEpochSecond();
О java.time
Рамка java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют неприятные старые классы времени, такие как java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
Проект Joda-Time, теперь в режиме обслуживания, советует перейти на java.time.
Чтобы узнать больше, ознакомьтесь с учебным пособием Oracle. И поиск Qaru для многих примеров и объяснений.
Большая часть функциональных возможностей java.time была перенесена на Java 6 и 7 в ThreeTen-Backport и далее адаптирована для Android в ThreeTenABP (см. Как использовать...).
Проект ThreeTen-Extra расширяет java.time с дополнительными классами. Этот проект является доказательством возможных будущих дополнений к java.time. Здесь вы можете найти полезные классы, такие как Interval
, YearWeek
, YearQuarter
и другие.