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

4

Я хочу получить тот день, когда будет первый понедельник определенного месяца/года.

Что у меня есть:

Я в основном имею две переменные int, один из которых представляет год и один, представляющий месяц.

Что я хочу иметь:

Я хочу знать первый понедельник в этом месяце, желательно как значение int или Integer.

Например:

У меня есть 2014 год и 1 (январь), первый понедельник этого месяца был 6-м, поэтому я хочу вернуться 6.

Проблемы:

Я думал, что смогу сделать это с помощью Calendar но у меня уже возникли проблемы с настройкой календаря с доступным только годом и месяцем. Кроме того, я не уверен, как фактически вернуть первый понедельник месяца/года в Calendar.

Я уже пробовал это:

Calendar cal = Calendar.getInstance();
cal.set(this.getYear(),getMonth(), 1);
int montag = cal.getFirstDayOfWeek();
for( int j = 0; j < 7; j++ ) {
    int calc = j - montag;
    if( calc < 0 ) {
        calc += 6;
    }
    weekDays[calc].setText(getDayString(calc));
}
  • 2
    Нет, getFirstDayOfWeek - это просто метод локализации. Смотрите документы: docs.oracle.com/javase/7/docs/api/java/util/…
  • 2
    Вы спрашиваете, что делает getFirstDayOfWeek ()? Javadoc сообщает, что: получает первый день недели; например, воскресенье в США, понедельник во Франции.
Показать ещё 2 комментария
Теги:

9 ответов

12
Лучший ответ

getFirstDayOfWeek() возвращает тот день, который используется как начало для текущей локали. Некоторые люди рассматривают первый день в понедельник, другие воскресенье и т.д.

Похоже, вам нужно просто установить его для DAY_OF_WEEK = MONDAY и DAY_OF_WEEK_IN_MONTH = 1 как это даст вам первый понедельник месяца. Чтобы сделать то же самое в течение года, сначала установите значение MONTH в JANUARY затем повторите описанное выше.

Пример:

private static Calendar cacheCalendar;

public static int getFirstMonday(int year, int month) {
    cacheCalendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    cacheCalendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
    cacheCalendar.set(Calendar.MONTH, month);
    cacheCalendar.set(Calendar.YEAR, year);
    return cacheCalendar.get(Calendar.DATE);
}

public static int getFirstMonday(int year) {
    return getFirstMonday(year, Calendar.JANUARY);
}

Вот простой JUnit, который его тестирует: http://pastebin.com/YpFUkjQG

  • 1
    Так или иначе, если я пытаюсь использовать этот метод, для параметров 2014 и 1 он возвращает 9, что не может быть правильным, поскольку неделя имеет только 7 дней.
  • 0
    Хм, позвольте мне проверить это. Это должно работать, но я отлажу это.
Показать ещё 5 комментариев
13

Java.time

Используйте библиотеку java.time встроенную в Java 8 и TemporalAdjuster. Смотрите учебник.

import java.time.DayOfWeek;
import java.time.LocalDate;
import static java.time.temporal.TemporalAdjusters.firstInMonth;

LocalDate now = LocalDate.now(); //2015-11-23
LocalDate firstMonday = now.with(firstInMonth(DayOfWeek.MONDAY)); //2015-11-02 (Monday)

Если вам нужно добавить информацию о времени, вы можете использовать любое доступное LocalDate в LocalDateTime например

firstMonday.atStartOfDay() # 2015-11-02T00:00
  • 0
    Я думаю, что следующая ссылка полезна. docs.oracle.com/javase/tutorial/datetime/iso/adjusters.html
  • 0
    @cybaek В Stack Overflow вам предлагается отредактировать ответ самостоятельно, чтобы добавить информацию, такую как ваша ссылка.
4

Прежде всего, вы должны знать последнюю версию java, т.е. JAVA8 Познакомьтесь с LocalDate в JAVA8

Затем пройдите только ниже кода

public class Test {

    public static void main(String[] args) {
        LocalDate date=LocalDate.of(2014,1, 1);
        for(int i=0;i<date.lengthOfMonth();i++){
            if("Monday".equalsIgnoreCase(date.getDayOfWeek().toString())){

                break;
            }else{
                date=date.plusDays(1);
            }
        }

        System.out.println(date.getDayOfMonth());

    }

}
  • 0
    Спасибо Василию за исправление опечатки :)
  • 0
    date.lengthOfMonth() ? но мы найдем понедельник в течение первых 7 дней любого месяца for(int i=0;i<7;i++){
2

Joda времени

Библиотека Joda-Time предлагает класс LocalDate, если вам нужна только дата без времени суток. Метод getDayOfWeek возвращает число, которое вы можете сравнить с константой MONDAY.

LocalDate localDate = new LocalDate( year, month, 1 );
while ( localDate.getDayOfWeek() != DateTimeConstants.MONDAY ) {
    localDate = localDate.plusDays( 1 );
}
int firstMonday = localDate.getDayOfMonth();

Неизменяемый синтаксис

Для обеспечения безопасности потоков Joda-Time использует неизменяемые объекты. Поэтому вместо изменения значений полей в существующем объекте мы создаем новый экземпляр, основанный на оригинале.

java.time

В другом ответе Abhishek Mishra говорится, что новый пакет java.time в комплекте с Java 8 также предлагает класс LocalDate подобный Joda-Time.

2

Метод getFirstDayOfWeek() не помогает. Цитируя его javadoc:

Получает то, что происходит в первый день недели; например, ВОСКРЕСЕНЬЕ в США, ПОНЕДЕЛЬНИК во Франции

Следующий проверенный метод использует арифметику модуля, чтобы найти день месяца первого понедельника:

public static long getMondaysDay(int year, int month) {
    try {
        Date d = new SimpleDateFormat("d-M-yyyy").parse("1-" + month + "-" + year);
        long epochMillis = d.getTime() + TimeZone.getDefault().getOffset(d.getTime());
        return (12 - TimeUnit.MILLISECONDS.toDays(epochMillis) % 7) % 7;
    } catch (ParseException ignore) { return 0; } // Never going to happen
}

Зная, что в первый день эпохи был четверг, это работает, используя арифметику модуля, чтобы рассчитать день недели, а затем сколько дней до следующего понедельника, затем снова модуль, если первый выпадет до четверга. Магическое число 12 - 4 (количество дней с четверга по понедельник) плюс 1 потому что дни месяца начинаются с 1 плюс 7 чтобы обеспечить положительные результаты после вычитания.

  • 0
    Учитывая различные способы смещения времени, я думаю, что использование Calendar будет более стабильным, чем преобразование миллисекунд с эпохи в день.
  • 0
    @ Не оставляйте в нашей жизни :) Кроме того, а) я люблю математику и б) я никогда не использую класс Calendar в принципе
Показать ещё 5 комментариев
1

Самый простой способ:

LocalDate firstSundayOfNextMonth = LocalDate
              .now()
              .with(firstDayOfNextMonth())
              .with(nextOrSame(DayOfWeek.MONDAY));
0

Вот общая функция для получения n-го DAY_OF_WEEK заданного месяца. Вы можете использовать его, чтобы получить первый понедельник любого месяца.

import java.util.Calendar;

public class NthDayOfWeekOfMonth {

public static void main(String[] args) {
    // get first Monday of July 2019
    Calendar cal = getNthDayOfWeekOfMonth(2019,Calendar.JULY,1,Calendar.MONDAY);
    System.out.println(cal.getTime());

    // get first Monday of August 2019
    cal = getNthDayOfWeekOfMonth(2019,Calendar.AUGUST,1,Calendar.MONDAY);
    System.out.println(cal.getTime());

    // get third Friday of September 2019
    cal = getNthDayOfWeekOfMonth(2019,Calendar.SEPTEMBER,3,Calendar.FRIDAY);
    System.out.println(cal.getTime());
}

public static Calendar getNthDayOfWeekOfMonth(int year, int month, int n, int dayOfWeek) {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE,0);
    cal.set(Calendar.SECOND,0);
    cal.set(Calendar.YEAR,year);
    cal.set(Calendar.MONTH,month);
    cal.set(Calendar.DAY_OF_MONTH,1);

    int dayDiff = dayOfWeek-cal.get(Calendar.DAY_OF_WEEK);
    if (dayDiff<0) {
        dayDiff+=7;
    }
    dayDiff+=7*(n-1);

    cal.add(Calendar.DATE, dayDiff); 
    return cal;
}

}

Выход:

Mon Jul 01 00:00:00 EDT 2019
Mon Aug 05 00:00:00 EDT 2019
Fri Sep 20 00:00:00 EDT 2019
0
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("MMM/dd/YYYY");
        calendar.set(Calendar.MONTH,Calendar.JUNE);
        calendar.set(Calendar.DAY_OF_MONTH,1);          
        int day = (Calendar.TUESDAY-calendar.get(Calendar.DAY_OF_WEEK));            
        if(day<0){
          calendar.add(Calendar.DATE,7+(day));
        }else{
            calendar.add(Calendar.DATE,day);
        }
        System.out.println("First date is "+sdf.format(calendar.getTime()));
0

Библиотека Lamma Date очень хороша для этого варианта использования.

@Test
public void test() {
    assertEquals(new Date(2014, 1, 6), firstMonday(2014, 1));
    assertEquals(new Date(2014, 2, 3), firstMonday(2014, 2));
    assertEquals(new Date(2014, 3, 3), firstMonday(2014, 3));
    assertEquals(new Date(2014, 4, 7), firstMonday(2014, 4));
    assertEquals(new Date(2014, 5, 5), firstMonday(2014, 5));
    assertEquals(new Date(2014, 6, 2), firstMonday(2014, 6));
}

public Date firstMonday(int year, int month) {
    Date firstDayOfMonth = new Date(year, month, 1);
    return firstDayOfMonth.nextOrSame(DayOfWeek.MONDAY);
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню