Я хочу получить тот день, когда будет первый понедельник определенного месяца/года.
Что у меня есть:
Я в основном имею две переменные 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));
}
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
Используйте библиотеку 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
Прежде всего, вы должны знать последнюю версию 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());
}
}
date.lengthOfMonth()
? но мы найдем понедельник в течение первых 7 дней любого месяца for(int i=0;i<7;i++){
Библиотека 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 использует неизменяемые объекты. Поэтому вместо изменения значений полей в существующем объекте мы создаем новый экземпляр, основанный на оригинале.
В другом ответе Abhishek Mishra говорится, что новый пакет java.time в комплекте с Java 8 также предлагает класс LocalDate
подобный Joda-Time.
Метод 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
чтобы обеспечить положительные результаты после вычитания.
Calendar
будет более стабильным, чем преобразование миллисекунд с эпохи в день.
Самый простой способ:
LocalDate firstSundayOfNextMonth = LocalDate
.now()
.with(firstDayOfNextMonth())
.with(nextOrSame(DayOfWeek.MONDAY));
Вот общая функция для получения 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
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()));
Библиотека 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);
}
getFirstDayOfWeek
- это просто метод локализации. Смотрите документы: docs.oracle.com/javase/7/docs/api/java/util/…