Как получить первый день текущей недели и месяца?
У меня есть дата нескольких событий, выраженная в миллисекундах[1], и я хочу знать, какие события находятся внутри текущей недели и текущего месяца, но я не могу понять, как получить первый день (день / месяц / год)) текущей недели и конвертируйте ее в миллисекунды, то же самое для первого дня месяца.
[1]Since January 1, 1970, 00:00:00 GMT
12 ответов
Эта неделя в миллисекундах:
// get today and clear time of day
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0); // ! clear would not reset the hour of day !
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
// get start of this week in milliseconds
cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
System.out.println("Start of this week: " + cal.getTime());
System.out.println("... in milliseconds: " + cal.getTimeInMillis());
// start of the next week
cal.add(Calendar.WEEK_OF_YEAR, 1);
System.out.println("Start of the next week: " + cal.getTime());
System.out.println("... in milliseconds: " + cal.getTimeInMillis());
Этот месяц в миллисекундах:
// get today and clear time of day
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0); // ! clear would not reset the hour of day !
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
// get start of the month
cal.set(Calendar.DAY_OF_MONTH, 1);
System.out.println("Start of the month: " + cal.getTime());
System.out.println("... in milliseconds: " + cal.getTimeInMillis());
// get start of the next month
cal.add(Calendar.MONTH, 1);
System.out.println("Start of the next month: " + cal.getTime());
System.out.println("... in milliseconds: " + cal.getTimeInMillis());
Первый день недели можно определить с помощью java.util.Calendar
следующее:
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.setTimeInMillis(timestamp);
while (calendar.get(Calendar.DAY_OF_WEEK) > calendar.getFirstDayOfWeek()) {
calendar.add(Calendar.DATE, -1); // Substract 1 day until first day of week.
}
long firstDayOfWeekTimestamp = calendar.getTimeInMillis();
Первый день месяца можно определить следующим образом:
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.setTimeInMillis(timestamp);
while (calendar.get(Calendar.DATE) > 1) {
calendar.add(Calendar.DATE, -1); // Substract 1 day until first day of month.
}
long firstDayOfMonthTimestamp = calendar.getTimeInMillis();
Довольно многословно, да.
Java 7 будет иметь значительно улучшенный API даты и времени ( JSR-310). Если вы еще не можете переключиться, то можете использовать JodaTime, что делает все это менее сложным:
DateTime dateTime = new DateTime(timestamp);
long firstDayOfWeekTimestamp = dateTime.withDayOfWeek(1).getMillis();
а также
DateTime dateTime = new DateTime(timestamp);
long firstDayOfMonthTimestamp = dateTime.withDayOfMonth(1).getMillis();
java.time
Среда java.time в Java 8 и более поздних версиях заменяет старые классы java.util.Date/.Calendar. Старые классы оказались неприятными, запутанными и ошибочными. Избежать их.
Инфраструктура java.time основана на очень успешной библиотеке Joda-Time, определенной в JSR 310, расширенной проектом ThreeTen-Extra и объясненной в Учебном руководстве.
Instant
Instant
класс представляет момент на временной шкале в UTC.
Фреймворк java.time имеет разрешение наносекунд или 9 цифр доли секунды. Миллисекунды - это всего лишь 3 цифры доли секунды. Поскольку разрешение в миллисекундах является обычным, java.time включает удобный заводской метод.
long millisecondsSinceEpoch = 1446959825213L;
Instant instant = Instant.ofEpochMilli ( millisecondsSinceEpoch );
миллисекундыС начала эпохи: 1446959825213 мгновенно: 2015-11-08T05:17:05.213Z
ZonedDateTime
Чтобы учесть текущую неделю и текущий месяц, нам нужно применить определенный часовой пояс.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
В zoneId: Америка / Монреаль: 2015-11-08T00:17:05.213-05:00[Америка / Монреаль]
Полуоткрытый
В работе с датой и временем мы обычно используем подход Half-Open для определения промежутка времени. Начало включительно, а окончание - эксклюзив. Вместо того, чтобы пытаться определить последнюю долю секунды в конце недели (или месяца), мы получаем первый момент следующей недели (или месяца). Таким образом, неделя начинается с первого момента понедельника и продолжается, но не включает первый момент следующего понедельника.
Давайте первый день недели и последний. Среда java.time включает в себя инструмент для этого, with
метод и ChronoField
ENUM.
По умолчанию java.time использует стандарт ISO 8601. Таким образом, понедельник - первый день недели (1), а воскресенье - последнее (7).
ZonedDateTime firstOfWeek = zdt.with ( ChronoField.DAY_OF_WEEK , 1 ); // ISO 8601, Monday is first day of week.
ZonedDateTime firstOfNextWeek = firstOfWeek.plusWeeks ( 1 );
Эта неделя начинается с: 2015-11-02T00:17:05.213-05:00[Америка / Монреаль] до 2015-11-09T00:17:05.213-05:00[Америка / Монреаль]
К сожалению! Посмотрите на время суток на эти значения. Мы хотим первый момент дня. Первый момент дня не всегда 00:00:00.000
из-за перехода на летнее время (DST) или других аномалий. Поэтому мы должны позволить java.time внести коррективы от нашего имени. Чтобы сделать это, мы должны пройти через LocalDate
учебный класс.
ZonedDateTime firstOfWeek = zdt.with ( ChronoField.DAY_OF_WEEK , 1 ); // ISO 8601, Monday is first day of week.
firstOfWeek = firstOfWeek.toLocalDate ().atStartOfDay ( zoneId );
ZonedDateTime firstOfNextWeek = firstOfWeek.plusWeeks ( 1 );
Эта неделя начинается с: 2015-11-02T00:00-05:00[Америка / Монреаль] до 2015-11-09T00:00-05:00[Америка / Монреаль]
И то же самое за месяц.
ZonedDateTime firstOfMonth = zdt.with ( ChronoField.DAY_OF_MONTH , 1 );
firstOfMonth = firstOfMonth.toLocalDate ().atStartOfDay ( zoneId );
ZonedDateTime firstOfNextMonth = firstOfMonth.plusMonths ( 1 );
Этот месяц начинается с: 2015-11-01T00:00-04:00[Америка / Монреаль] до 2015-12-01T00:00-05:00[Америка / Монреаль]
YearMonth
Еще один способ узнать, есть ли пара моментов в одном месяце, - это проверить YearMonth
значение.
Например, предполагая thisZdt
а также thatZdt
оба ZonedDateTime
объекты:
boolean inSameMonth = YearMonth.from( thisZdt ).equals( YearMonth.from( thatZdt ) ) ;
миллисекунды
Я настоятельно рекомендую не делать вашу работу с датой и временем в миллисекундах от эпохи. Именно так классы даты и времени работают внутри, но у нас есть причины по причине. Обработка отсчетов из эпохи неуклюжа, поскольку значения не понятны людям, поэтому отладка и ведение журнала трудны и подвержены ошибкам. И, как мы уже видели, могут быть разные разрешения; старые классы Java и библиотека Joda-Time используют миллисекунды, в то время как базы данных, такие как Postgres, используют микросекунды, а теперь java.time использует наносекунды.
Будете ли вы обрабатывать текст как биты, или вы позволите такие классы, как String
, StringBuffer
, а также StringBuilder
обрабатывать такие детали?
Но если вы настаиваете, от ZonedDateTime
получить Instant
и из этого получим миллисекунды-отсчет от эпохи. Но имейте в виду, что этот вызов может означать потерю данных. Любые микросекунды или наносекунды, которые вы можете иметь в своем ZonedDateTime
/ Instant
будет усечено (потеряно).
long millis = firstOfWeek.toInstant().toEpochMilli(); // Possible data loss.
Внимание!
while (calendar.get(Calendar.DAY_OF_WEEK) > calendar.getFirstDayOfWeek()) {
calendar.add(Calendar.DATE, -1); // Substract 1 day until first day of week.
}
Это хорошая идея, но есть некоторая проблема: например, я из Украины и calendar.getFirstDayOfWeek() в моей стране - 2 (понедельник). И сегодня 1 (воскресенье). В этом случае calendar.add не вызывается.
Таким образом, правильный путь - это заменить ">" на "!=":
while (calendar.get(Calendar.DAY_OF_WEEK) != calendar.getFirstDayOfWeek()) {...
Вы можете использовать java.time
пакет (начиная с Java8 и позже), чтобы получить начало / конец дня / недели / месяца.
Пример класса util ниже:
import org.junit.Test;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
public class DateUtil {
private static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("UTC");
public static LocalDateTime startOfDay() {
return LocalDateTime.now(DEFAULT_ZONE_ID).with(LocalTime.MIN);
}
public static LocalDateTime endOfDay() {
return LocalDateTime.now(DEFAULT_ZONE_ID).with(LocalTime.MAX);
}
public static boolean belongsToCurrentDay(final LocalDateTime localDateTime) {
return localDateTime.isAfter(startOfDay()) && localDateTime.isBefore(endOfDay());
}
//note that week starts with Monday
public static LocalDateTime startOfWeek() {
return LocalDateTime.now(DEFAULT_ZONE_ID)
.with(LocalTime.MIN)
.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
}
//note that week ends with Sunday
public static LocalDateTime endOfWeek() {
return LocalDateTime.now(DEFAULT_ZONE_ID)
.with(LocalTime.MAX)
.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
}
public static boolean belongsToCurrentWeek(final LocalDateTime localDateTime) {
return localDateTime.isAfter(startOfWeek()) && localDateTime.isBefore(endOfWeek());
}
public static LocalDateTime startOfMonth() {
return LocalDateTime.now(DEFAULT_ZONE_ID)
.with(LocalTime.MIN)
.with(TemporalAdjusters.firstDayOfMonth());
}
public static LocalDateTime endOfMonth() {
return LocalDateTime.now(DEFAULT_ZONE_ID)
.with(LocalTime.MAX)
.with(TemporalAdjusters.lastDayOfMonth());
}
public static boolean belongsToCurrentMonth(final LocalDateTime localDateTime) {
return localDateTime.isAfter(startOfMonth()) && localDateTime.isBefore(endOfMonth());
}
public static long toMills(final LocalDateTime localDateTime) {
return localDateTime.atZone(DEFAULT_ZONE_ID).toInstant().toEpochMilli();
}
public static Date toDate(final LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(DEFAULT_ZONE_ID).toInstant());
}
public static String toString(final LocalDateTime localDateTime) {
return localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
}
@Test
public void test() {
//day
final LocalDateTime now = LocalDateTime.now();
System.out.println("Now: " + toString(now) + ", in mills: " + toMills(now));
System.out.println("Start of day: " + toString(startOfDay()));
System.out.println("End of day: " + toString(endOfDay()));
System.out.println("Does '" + toString(now) + "' belong to the current day? > " + belongsToCurrentDay(now));
final LocalDateTime yesterday = now.minusDays(1);
System.out.println("Does '" + toString(yesterday) + "' belong to the current day? > " + belongsToCurrentDay(yesterday));
final LocalDateTime tomorrow = now.plusDays(1);
System.out.println("Does '" + toString(tomorrow) + "' belong to the current day? > " + belongsToCurrentDay(tomorrow));
//week
System.out.println("Start of week: " + toString(startOfWeek()));
System.out.println("End of week: " + toString(endOfWeek()));
System.out.println("Does '" + toString(now) + "' belong to the current week? > " + belongsToCurrentWeek(now));
final LocalDateTime previousWeek = now.minusWeeks(1);
System.out.println("Does '" + toString(previousWeek) + "' belong to the current week? > " + belongsToCurrentWeek(previousWeek));
final LocalDateTime nextWeek = now.plusWeeks(1);
System.out.println("Does '" + toString(nextWeek) + "' belong to the current week? > " + belongsToCurrentWeek(nextWeek));
//month
System.out.println("Start of month: " + toString(startOfMonth()));
System.out.println("End of month: " + toString(endOfMonth()));
System.out.println("Does '" + toString(now) + "' belong to the current month? > " + belongsToCurrentMonth(now));
final LocalDateTime previousMonth = now.minusMonths(1);
System.out.println("Does '" + toString(previousMonth) + "' belong to the current month? > " + belongsToCurrentMonth(previousMonth));
final LocalDateTime nextMonth = now.plusMonths(1);
System.out.println("Does '" + toString(nextMonth) + "' belong to the current month? > " + belongsToCurrentMonth(nextMonth));
}
}
Тестовый результат:
Now: 2020-02-16T22:12:49.957, in mills: 1581891169957
Start of day: 2020-02-16T00:00:00
End of day: 2020-02-16T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current day? > true
Does '2020-02-15T22:12:49.957' belong to the current day? > false
Does '2020-02-17T22:12:49.957' belong to the current day? > false
Start of week: 2020-02-10T00:00:00
End of week: 2020-02-16T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current week? > true
Does '2020-02-09T22:12:49.957' belong to the current week? > false
Does '2020-02-23T22:12:49.957' belong to the current week? > false
Start of month: 2020-02-01T00:00:00
End of month: 2020-02-29T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current month? > true
Does '2020-01-16T22:12:49.957' belong to the current month? > false
Does '2020-03-16T22:12:49.957' belong to the current month? > false
I have created some methods for this:
public static String catchLastDayOfCurrentWeek(String pattern) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
return calendarToString(cal, pattern);
}
public static String catchLastDayOfCurrentWeek(String pattern) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
cal.add(Calendar.WEEK_OF_YEAR, 1);
cal.add(Calendar.MILLISECOND, -1);
return calendarToString(cal, pattern);
}
public static String catchTheFirstDayOfThemonth(Integer month, pattern padrao) {
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(new Date());
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DAY_OF_MONTH, 1);
return calendarToString(cal, pattern);
}
public static String catchTheLastDayOfThemonth(Integer month, String pattern) {
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(new Date());
cal.set(cal.get(Calendar.YEAR), month, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
return calendarToString(cal, pattern);
}
public static String calendarToString(Calendar calendar, String pattern) {
if (calendar == null) {
return "";
}
SimpleDateFormat format = new SimpleDateFormat(pattern, LocaleUtils.DEFAULT_LOCALE);
return format.format(calendar.getTime());
}
Вы можете увидеть больше здесь.
Чтобы получить первый день месяца, просто получите Date
и установите текущий день в день 1 месяца. Очистите часы, минуты, секунды и миллисекунды, если вам это нужно.
private static Date firstDayOfMonth(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.DATE, 1);
return calendar.getTime();
}
Первый день недели это то же самое, но с использованием Calendar.DAY_OF_WEEK
вместо
private static Date firstDayOfWeek(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.DAY_OF_WEEK, 1);
return calendar.getTime();
}
Однострочное решение с использованием функций Java 8
В Java
LocalDateTime firstOfWeek = LocalDateTime.now().with(ChronoField.DAY_OF_WEEK, 1).toLocalDate().atStartOfDay(); // 2020-06-08 00:00 MONDAY
LocalDateTime firstOfMonth = LocalDateTime.now().with(ChronoField.DAY_OF_MONTH , 1).toLocalDate().atStartOfDay(); // 2020-06-01 00:00
// Convert to milliseconds:
firstOfWeek.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
В Котлине
val firstOfWeek = LocalDateTime.now().with(ChronoField.DAY_OF_WEEK, 1).toLocalDate().atStartOfDay() // 2020-06-08 00:00 MONDAY
val firstOfMonth = LocalDateTime.now().with(ChronoField.DAY_OF_MONTH , 1).toLocalDate().atStartOfDay() // 2020-06-01 00:00
// Convert to milliseconds:
firstOfWeek.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
В этом случае:
// get today and clear time of day
Calendar cal = Calendar.getInstance();
cal.clear(Calendar.HOUR_OF_DAY); <---- is the current hour not 0 hour
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
Таким образом, Calendar.HOUR_OF_DAY возвращает 8, 9, 12, 15, 18 как текущий рабочий час. Я думаю, что будет лучше изменить такую строку путем:
c.set(Calendar.HOUR_OF_DAY,0);
таким образом, день всегда начинается в 0 часов
Получить первую дату следующего месяца:-
SimpleDateFormat df = new SimpleDateFormat("MM-dd-yyyy");
String selectedDate="MM-dd-yyyy like 07-02-2018";
Date dt = df.parse(selectedDate);`enter code here`
calendar = Calendar.getInstance();
calendar.setTime(dt);
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
String firstDate = df.format(calendar.getTime());
System.out.println("firstDateof next month ==>" + firstDate);
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Scanner;
/**
This Program will display day for, 1st and last days in a given month and year
@author Manoj Kumar Dunna
Mail Id : manojdunna@gmail.com
*/
public class DayOfWeek {
public static void main(String[] args) {
String strDate = null;
int year = 0, month = 0;
Scanner sc = new Scanner(System.in);
System.out.print("Enter YYYY/MM: ");
strDate = sc.next();
Calendar cal = new GregorianCalendar();
String [] date = strDate.split("/");
year = Integer.parseInt(date[0]);
month = Integer.parseInt(date[1]);
cal.set(year, month-1, 1);
System.out.println(new SimpleDateFormat("EEEE").format(cal.getTime()));
cal.add(Calendar.MONTH, 1);
cal.add(Calendar.DAY_OF_YEAR, -1);
System.out.println(new SimpleDateFormat("EEEE").format(cal.getTime()));
}
}
Вы должны быть в состоянии преобразовать свой номер в календарь Java, например:
Calendar.getInstance().setTimeInMillis(myDate);
Оттуда сравнение не должно быть слишком сложным.
Simple Solution:
package com.util.calendarutil;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class CalUtil {
public static void main(String args[]){
DateFormat df = new SimpleDateFormat("dd/mm/yyyy");
Date dt = null;
try {
dt = df.parse("23/01/2016");
} catch (ParseException e) {
System.out.println("Error");
}
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
Date startDate = cal.getTime();
cal.add(Calendar.DATE, 6);
Date endDate = cal.getTime();
System.out.println("Start Date:"+startDate+"End Date:"+endDate);
}
}
Я использую этот трюк, чтобы получить первый день текущего месяца, обратите внимание, что порядок 1 для воскресенья 2, понедельника 3 для вторника... и так далее.
Calendar cal = new GregorianCalendar();
int startDay = cal.get(Calendar.DAY_OF_YEAR) % 7 + 1;
System.out.println(startDay);
public static void main(String[] args) {
System.out.println(getMonthlyEpochList(1498867199L,12,"Monthly"));
}
public static Map<String,String> getMonthlyEpochList(Long currentEpoch, int noOfTerms, String timeMode) {
Map<String,String> map = new LinkedHashMap<String,String>();
int month = 0;
while(noOfTerms != 0) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, month);
calendar.set(Calendar.DATE, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
Date monthFirstDay = calendar.getTime();
calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
Date monthLastDay = calendar.getTime();
map.put(getMMYY(monthFirstDay.getTime()), monthFirstDay + ":" +monthLastDay);
month--;
noOfTerms--;
}
return map;
}