检查日期是否在范围内
Checking dates if it is in a range
我的 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 天或更长时间。
定义两个格式化程序。一个 Fromatter 从 edittext 获取日期和时间。等到当天凌晨 12 点。现在我们需要对应于同一天早上 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;
你应该使用新的 DateTimeFormatter
class 来给你一个 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;
您可以检查LocalTime
part of a LocalDateTime
to have a simple check using isAfter
and 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");
}
NIGHT TIME
输出有效,因为我们从 23:00 开始并在 05:00 结束。
如果您需要为 5:45
定义类似 LocalTime.of(5,45)
的时间,则使用此方法可以提供更简单的解决方案
这是一个例子,如果允许从第 22 部分开始但在第 6 部分之后继续工作,这可能需要一些调整。这只是一个关于如何使用这些方法的例子。
如果您使用 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());
我试图满足您的所有要求。我在阅读之前编写了代码,您不需要考虑夏令时 (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 小时作为夜间时间。确实代码打印
Day 32.0 hours; night 12.5 hours
程序如下。请在我输入 America/Monterey.
的地方填写正确的时区
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);
}
我的 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 天或更长时间。
定义两个格式化程序。一个 Fromatter 从 edittext 获取日期和时间。等到当天凌晨 12 点。现在我们需要对应于同一天早上 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;
你应该使用新的 DateTimeFormatter
class 来给你一个 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;
您可以检查LocalTime
part of a LocalDateTime
to have a simple check using isAfter
and 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");
}
NIGHT TIME
输出有效,因为我们从 23:00 开始并在 05:00 结束。
如果您需要为 5:45
定义类似LocalTime.of(5,45)
的时间,则使用此方法可以提供更简单的解决方案
这是一个例子,如果允许从第 22 部分开始但在第 6 部分之后继续工作,这可能需要一些调整。这只是一个关于如何使用这些方法的例子。
如果您使用 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());
我试图满足您的所有要求。我在阅读之前编写了代码,您不需要考虑夏令时 (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 小时作为夜间时间。确实代码打印
Day 32.0 hours; night 12.5 hours
程序如下。请在我输入 America/Monterey.
的地方填写正确的时区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);
}