Проверка дат, если он находится в диапазоне - PullRequest
0 голосов
/ 30 апреля 2018

Мое приложение Java FX обрабатывает отработанные часы. У меня есть время начала и окончания работы в 2 полях даты. Мне удалось рассчитать разницу между 2 dateTime; но теперь, как я могу проверить, находится ли результат в ночном или дневном диапазоне? День начинается в 6 и заканчивается в 22 часа. Например, тот, кто работал с 3 утра до 11 вечера. Ниже показано, как я сделал, чтобы общее количество отработанных часов.

public void CalculNbreJourTravaille() {
    SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyy HH:mm");

    try {
        Date ddtt = format.parse(ddt.getText());
        Date dftt = format.parse(dft.getText());
        long diff = dftt.getTime() - ddtt.getTime();
        long diffhours = diff / (60*60*1000)%24;
        long diffdays = diff/(24*60*60*1000);
        long total = diffhours + (diffdays*24);
        result.setText(total + " Hours");   
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

У нас есть работники, которые могут работать после 10 вечера, и оплата не будет такой же. Если они работают после 10 вечера, им будет выплачиваться специальная оплата. Мы платим в конце работы. Они могли бы работать только 10 дней или больше.

Ответы [ 5 ]

0 голосов
/ 30 апреля 2018

Вот моя попытка удовлетворить все ваши требования. Перед написанием кода я написал, что вам не требуется учитывать летнее время (DST), поэтому я использую ZonedDateTime для получения правильных часов и при переходах на летнее время. По той же причине мне нужно повторять каждый день. Для каждой даты я рассчитываю часы, отработанные в ночное время, и часы, отработанные в дневное время.

Если вы хотите убедиться, что летнее время не учитывается , используйте LocalDateTime вместо ZonedDateTime. В этом случае возможен прирост производительности при расчете целых рабочих дней одним комком, а не одним днем ​​за один раз.

Приведенный ниже код использует 28/03/2018 03:00 и 29/03/2018 23:30 в качестве примера времени начала и окончания. Ожидаемое общее количество отработанных часов составляет 44,5, поскольку один день составляет 24 часа, а с 03:00 до 23:30 - 20,5 часов. Ожидаемое дневное время составляет 32, поскольку каждый из двух дней имеет 16 дневных часов. Это оставляет 12,5 часов в ночное время. И действительно, код печатает

день 32,0 часа; ночь 12,5 часа

Программа следующая. Пожалуйста, заполните правильный часовой пояс, в который я поместил Америку / Монтерей.

static ZoneId zone = ZoneId.of("America/Monterrey");
static LocalTime dayStart = LocalTime.of(6, 0);
static LocalTime dayEnd = LocalTime.of(22, 0);
static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/uuuu H:mm");

public static void main(String[] args) {

    String workStartString = "28/03/2018 03:00";
    String workEndString = "29/03/2018 23:30";
    calculateWorkingHours(workStartString, workEndString);
}

public static void calculateWorkingHours(String workStartString, String workEndString) {
    ZonedDateTime workStart
            = LocalDateTime.parse(workStartString, formatter).atZone(zone);
    ZonedDateTime workEnd
            = LocalDateTime.parse(workEndString, formatter).atZone(zone);

    if (workEnd.isBefore(workStart)) {
        throw new IllegalArgumentException("Work end must not be before work start");
    }

    LocalDate workStartDate = workStart.toLocalDate();
    LocalDate workEndDate = workEnd.toLocalDate();

    Duration workedDaytime = Duration.ZERO;
    // first calculate work at nighttime before the start date, that is, work before 06:00
    Duration workedNighttime 
            = calculateNightTime(workStartDate.minusDays(1), workStart, workEnd);

    for (LocalDate d = workStartDate; ! d.isAfter(workEndDate); d = d.plusDays(1)) {
        workedDaytime = workedDaytime.plus(calculateDayTime(d, workStart, workEnd));
        workedNighttime = workedNighttime.plus(calculateNightTime(d, workStart, workEnd));
    }

    double dayHours = workedDaytime.toMinutes() / (double) TimeUnit.HOURS.toMinutes(1);
    double nightHours = workedNighttime.toMinutes() / (double) TimeUnit.HOURS.toMinutes(1);

    System.out.println("Day " + dayHours + " hours; night " + nightHours + " hours");

}

/**
 * Calculates amount of work in daytime on d,
 * that is between 06:00 and 22:00 on d.
 * Only time that falls with in workStart to workAnd
 * and also falls within 06:00 to 22:00 on d is included.
 * 
 * @param d The date for which to calculate day work
 * @param workStart
 * @param workEnd
 * @return Amount of daytime work on the said day
 */
private static Duration calculateDayTime(LocalDate d, ZonedDateTime workStart, ZonedDateTime workEnd) {
    ZonedDateTime dayStartToday = d.atTime(dayStart).atZone(zone);
    ZonedDateTime dayEndToday = d.atTime(dayEnd).atZone(zone);
    if (workStart.isAfter(dayEndToday) || workEnd.isBefore(dayStartToday)) {
        return Duration.ZERO;
    }

    // restrict calculation to daytime on d
    if (workStart.isBefore(dayStartToday)) {
        workStart = dayStartToday;
    }
    if (workEnd.isAfter(dayEndToday)) {
        workEnd = dayEndToday;
    }

    return Duration.between(workStart, workEnd);
}

/**
 * Calculates amount of night work in the night after d,
 * that is from 22:00 on d until 06:00 the next morning.
 * 
 * @param d The date for which to calculate night work
 * @param workStart
 * @param workEnd
 * @return Amount of nighttime work in said night
 */
private static Duration calculateNightTime(LocalDate d, ZonedDateTime workStart, ZonedDateTime workEnd) {
    assert ! workEnd.isBefore(workStart);

    ZonedDateTime nightStart = d.atTime(dayEnd).atZone(zone);
    ZonedDateTime nightEnd = d.plusDays(1).atTime(dayStart).atZone(zone);

    if (workEnd.isBefore(nightStart) || workStart.isAfter(nightEnd)) {
        return Duration.ZERO;
    }

    // restrict calculation to the night after d
    if (workStart.isBefore(nightStart)) {
        workStart = nightStart;
    }
    if (workEnd.isAfter(nightEnd)) {
        workEnd = nightEnd;
    }

    return Duration.between(workStart, workEnd);
}
0 голосов
/ 30 апреля 2018

Это проще, если вы используете java.time API. Вам просто нужно проверить, отличаются ли даты или время начала не в диапазоне от 6:00 до 22:00:

private static final LocalTime START_TIME = LocalTime.of(6, 0); // 06:00
private static final LocalTime END_TIME = LocalTime.of(22, 0); // 22:00
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
// parse from input strings
LocalDateTime start = LocalDateTime.parse(startText, FORMATTER);
LocalDateTime end = LocalDateTime.parse(endText, FORMATTER);

boolean nightTime = 
        !start.toLocalDate().equals(end.toLocalDate())
        || start.toLocalTime().isBefore(START_TIME)
        || end.toLocalTime().isAfter(END_TIME);

// todo: change output to gui
System.out.println("night time: " + nightTime);
System.out.println("duration  : " + Duration.between(start, end).toHours());
0 голосов
/ 30 апреля 2018

Вы должны использовать новый класс DateTimeFormatter, чтобы получить объект LocalDateTime, с которого вы можете извлечь час.

DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
LocalDateTime localDateTimeFrom = format.parse(dateFrom.getText(), LocalDateTime::from);
LocalDateTime localDateTimeTo = format.parse(dateTo.getText(), LocalDateTime::from);

int hoursFrom = localDateTimeFrom.getHour();
int hoursTo = localDateTimeTo.getHour();

boolean workedNight = hoursFrom < 6 || hoursTo > 22;
0 голосов
/ 30 апреля 2018

Вы можете проверить LocalTime часть LocalDateTime, чтобы выполнить простую проверку, используя isAfter и isBefore .

Я буду использовать эти значения в этом примере.

LocalDateTime start = LocalDateTime.of(2018, Month.APRIL, 30, 23, 0);
LocalDateTime end = LocalDateTime.of(2018, Month.MAY, 1, 5, 0);

Затем определите предел для ночи.

LocalTime startNight = LocalTime.of(22, 0);
LocalTime endNight = LocalTime.of(6, 0);

И просто используйте, получите LocalTime обеих дат и проверьте, находятся ли они в диапазоне. Вы можете получить значение, используя toLocalTime.

if(start.toLocalTime().isAfter(startNight) &&
        end.toLocalTime().isBefore(endNight)){
    System.out.println("NIGHT TIME");
} else {
    System.out.println("DAY TIME");
}

НОЧНОЕ ВРЕМЯ

Вывод действителен, поскольку мы начинаем в 23:00 и заканчиваем в 05:00.


Использование этого позволяет более простое решение, если вам нужно определить время как LocalTime.of(5,45) для 5: 45

Это пример, может потребоваться некоторая адаптация, если разрешено начинать часть 22, но продолжать работать после 6. Это всего лишь пример того, как использовать эти методы.

0 голосов
/ 30 апреля 2018

Определить два форматера. Один Fromatter, чтобы получить дату со временем из edittext. И другие, чтобы получить 12 утра этого дня. Теперь нам нужны объекты Date, соответствующие 6 утра и 11 вечера того же дня. Мы можем получить их, добавив столько миллисекунд к объекту 12AM. Эти добавленные даты можно использовать для сравнения.

SimpleDateFormat df_zero_hours = new SimpleDateFormat("dd/MM/yyy");
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");

Date ddtt = format.parse(ddt.getText()); //Work Start Time
Date dftt = format.parse(dft.getText()); //Work End Time


Date dateStart = df_zero_hours.parse(ddt.getText()); //12AM of the day job started
Date dayStart = new Date();
    dayStart.setTime(dateStart.getTime()+6*60*60*1000); // Get 6AM of that day
Date dayEnd = new Date();
    dayEnd.setTime(dateStart.getTime()+22*60*60*1000); //Get 10PM of that day

//        Now check the worked hours. in Whatever way you need
boolean isBefore6AM = (dayStart.getTime()-ddtt.getTime())>0;
boolean isAfter10PM = (dftt.getTime()-dayEnd.getTime())>0;
...