Как получить первый день текущей недели и месяца? - PullRequest
66 голосов
/ 30 мая 2010

У меня есть дата нескольких событий, выраженная в миллисекундах [1], и я хочу знать, какие события находятся внутри текущей недели и текущего месяца, но я не могу понять, как получить первый день (день / месяц / год) текущей недели и преобразование его в миллисекунды, то же самое для первого дня месяца.

[1]Since January 1, 1970, 00:00:00 GMT

Ответы [ 13 ]

144 голосов
/ 30 мая 2010

На этой неделе в миллисекундах:

// 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());
23 голосов
/ 30 мая 2010

Первый день недели можно определить с помощью 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();
13 голосов
/ 08 ноября 2015

java.time

Инфраструктура java.time в Java 8 и более поздних версиях заменяет старые классы java.util.Date/.Calendar. Старые классы оказались проблематичными, запутанными и ошибочными. Избегайте их.

Фреймворк java.time создан на основе чрезвычайно успешной библиотеки Joda-Time , определенной JSR 310 , расширенной проектом ThreeTen-Extra и объяснено в Tutorial .

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

В работе с датой и временем мы обычно используем подход Half-Open для определения промежутка времени. Начало включительно , а окончание эксклюзив . Вместо того, чтобы пытаться определить последнюю долю секунды в конце недели (или месяца), мы получаем первый момент после недели (или месяца). Таким образом, неделя начинается с первого момента понедельника и поднимается до , но не включает первый момент после понедельника.

Давайте первый день недели и последний. Среда java.time включает в себя инструмент для этого, метод with и перечисление ChronoField.

По умолчанию 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 [Америка / Монреаль]

Oops! Посмотрите на время суток на эти значения. Мы хотим первый момент дня. Первый момент дня не всегда 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.

О 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?

11 голосов
/ 07 октября 2012

Внимание!

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()) {...
2 голосов
/ 06 декабря 2016

Я создал несколько методов для этого:

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());
}

Вы можете увидеть больше здесь .

2 голосов
/ 22 августа 2012

Чтобы получить первый день месяца, просто наберите 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();
}
1 голос
/ 02 мая 2018

Получить первую дату следующего месяца : -

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);
1 голос
/ 31 мая 2010

В этом случае:

// 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 часов

0 голосов
/ 09 июня 2019

я использую этот трюк, чтобы получить первый день текущего месяца обратите внимание, заказ 1 на воскресенье 2 на понедельник 3 на вторник .... и так далее

Calendar cal = new GregorianCalendar();
int startDay = cal.get(Calendar.DAY_OF_YEAR) % 7 + 1;
System.out.println(startDay);
0 голосов
/ 14 июня 2017
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;     
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...