Как получить первый день текущей недели и месяца?

У меня есть дата нескольких событий, выраженная в миллисекундах[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;     
}
Другие вопросы по тегам