java calendar - получите последние 5 дней недели (без выходных) - PullRequest
1 голос
/ 07 марта 2012

Я работаю с какой-то проблемой.

Мне нужно получить некоторые данные из базы данных

1) получить 5 записей за 5 последних дней (по одной записи в день), нодни должны быть днями недели (теперь выходными)

2) получить 20 записей за месяц (текущие или прошедшие, одна запись в день)

Я борюсь с JavaКалендарь, но я все еще не знаю, как получить даты.

Кто-нибудь может мне помочь?

Ответы [ 4 ]

2 голосов
/ 07 марта 2012

Должно работать:

private Calendar workingDaysBack(final Calendar from, final int count) {
    for (int daysBack = 0; daysBack < count; ++daysBack) {
        do {
            from.add(Calendar.DAY_OF_YEAR, -1);
        } while(isWeekend(from));
    }
    return from;
}

private boolean isWeekend(Calendar cal) {
    return cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||
           cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
}
1 голос
/ 27 февраля 2017

tl; dr

myLocalDate.with( 
    org.threeten.extra.Temporals.previousWorkingDay() 
)

Использование java.time

В других ответах используются проблемные старые классы даты и времени, такие как Calendar, которые сейчас унаследованы и вытеснены Java.классы времени.

Чтобы получить последние пять дней, сначала нужно получить «сегодня».

LocalDate

LocalDateclass представляет значение только для даты без времени суток и без часового пояса.

Часовой пояс имеет решающее значение при определении даты.В любой момент времени дата меняется по всему земному шару в зависимости от зоны.Например, через несколько минут после полуночи в Париж Франция - это новый день, в то время как "вчера" в Монреаль Квебек .

Укажите надлежащий часовой поясимя в формате continent/region, например America/Montreal, Africa/Casablanca или Pacific/Auckland.Никогда не используйте 3-4-буквенное сокращение, например EST или IST, так как они не истинных часовых поясов, не стандартизированы и даже не уникальны (!).

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );

DayOfWeek

Чтобы узнать предыдущие дни, вы можете позвонить по номеру minusDays для постепенного перемещения по датам в прошлом.

LocalDate yesterday = today.minusDays( 1 );
LocalDate dayBeforeYesterday = yesterday.minusDays( 1 );

Вы можете проверитькаждый LocalDate объект для своего дня недели, используя перечисление DayOfWeek.Этот класс предопределяет семь объектов, по одному на каждый день недели.Обратите внимание, что это реальные объекты, а не просто строки.Здесь вообще не нужно использовать строки.

Boolean isSaturday = myLocalDate.getDayOfWeek().equals( DayOfWeek.SATURDAY );
Boolean isSunday = myLocalDate.getDayOfWeek().equals( DayOfWeek.SUNDAY );

EnumSet

Более приятный и гибкий способ сравнения - с EnumSet,реализация Set, оптимизированная для перечислений, которая выполняется очень быстро и использует очень мало памяти.

EnumSet<DayOfWeek> weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY );

Используйте contains для проверки вашего LocalDate объекта DayOfWeek.

Boolean isWeekend = weekend.contains( myLocalDate.getDayOfWeek() );

ThreeTen-Extra TemporalAdjuster previousWorkingDay()

Проект ThreeTen-Extra расширяет классы java.time дополнительными функциями.В частности, здесь мы могли бы использовать previousWorkingDay реализацию интерфейса TemporalAdjuster.

Этот регулятор жестко задан для пропуска в субботу и воскресенье.Если вы хотите, чтобы учитывались другие значения дня недели, вы можете написать собственную реализацию TemporalAdjuster.

В классах java.time используются неизменяемые объекты.Поэтому вместо того, чтобы изменять значения («мутировать») объекта, мы генерируем новый объект со значениями, основанными на оригинале.Поэтому здесь мы вызываем LocalDate::with, передаем TemporalAdjuster и генерируем свежее LocalDate, которое представляет предыдущую дату при пропуске в субботу / воскресенье.

LocalDate previousWorkingDay = 
    myLocalDate.with( 
        org.threeten.extra.Temporals.previousWorkingDay() 
    ) 
;

Полный пример

Итак, давайте соберем все это вместе.

ZoneId z = ZoneId.of ( "America/Montreal" );
LocalDate today = LocalDate.now ( z );

Integer countDaysPrior = 5;
List<LocalDate> priorWeekdays = new ArrayList<> ( countDaysPrior ); // Set initial capacity to number of days to be collected.
LocalDate localDate = today; // Initialize to today. Exclusive, we want only prior days.
for ( int i = 1 ; i <= countDaysPrior ; i ++ ) {
    localDate = localDate.with ( org.threeten.extra.Temporals.previousWorkingDay () );  // Decrement each day into the past, skipping over Saturday/Sunday.
    priorWeekdays.add ( localDate );
}

System.out.println ( "Weekdays prior to " + today + " are: " + priorWeekdays );

Будние дни до 2017-02-27: [2017-02-24, 2017-02-23, 2017-02-22, 2017-02-21, 2017-02-20]

Полагаю, вы могли бы сделать этот код еще короче, используя Lambdas и Streams.


About java.time

Фреймворк java.time встроен в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .

Вы можете обмениваться java.time объектами непосредственно с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

1 голос
/ 07 марта 2012

Вы можете выполнить первую часть, просто настроив параметр дня недели для каждого дня, который вы хотите рассмотреть.Зависит от того, какое поведение вы хотите, если бегаете неделями - должна быть текущая неделя или последняя полная неделя?Здесь я предположил текущую неделю ...

Calendar cal = Calendar.getInstance();

List<Date> last5Days = new LinkedList<Date>();
List<Integer> weekDays = Arrays.asList(Calendar.MONDAY,
        Calendar.TUESDAY, Calendar.WEDNESDAY, Calendar.THURSDAY,
        Calendar.FRIDAY);
for (int weekDay : weekDays) {
    cal.set(Calendar.DAY_OF_WEEK, weekDay);
    last5Days.add(cal.getTime());
}
System.out.println(last5Days);

20 дней недели с текущего месяца.Зависит от того, какое поведение вы хотите на неделях, а не на месяц.Здесь я перешел к первому понедельнику, а затем добавил оттуда.

List<Date> last20Days = new LinkedList<Date>();
// find first Monday in the month
for (int i = 1; i <= 31; i++) {
    cal.set(Calendar.DAY_OF_MONTH, i);
    if (cal.get(Calendar.DAY_OF_WEEK) == weekDays.get(0)) {
        break;
    }
}
for (int i = 1; i <= 31; i++) {
    if (last20Days.size() == 20) {
        break;
    }
    if (weekDays.contains(cal.get(Calendar.DAY_OF_WEEK))) {
        last20Days.add(cal.getTime());
    }
    cal.add(Calendar.DAY_OF_MONTH, 1);
}
System.out.println(last20Days);
0 голосов
/ 07 марта 2012

Просто начало удара

Calendar cal = Calendar.getInstance();//initilized with current date & time
Date date = cal.getTime();//returned the current date & time that cal holds
boolean isMonday = Calendar.MONDAY == cal.get(Calendar.DAY_OF_WEEK);//it will return an integer 

Подробнее об API Doc

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...