有人可以幫我解決這個困惑嗎?我需要顯示每個工人的總作業時間。有不同的作業班次。在這種情況下,最復雜的是當人們從一天的 21:00 作業到第二天的 7:00 時的黎明轉變,考慮到日偏移,即在 10 月 31 日,瑞士有時間變化。我打算只在國內應用這個邏輯。以下代碼是否是這種情況的可靠解決方案?我曾嘗試了解 java.time 和針對此特定問題的許多帖子,但它們都變得更加混亂。
public String saveWorkTime(@Valid @ModelAttribute("workCalc") WorkCalculator workCalculator,
BindingResult bindingResult, ModelMap modelMap) throws ParseException {
(...)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date startDT = sdf.parse(workCalculator.getStartDate() " " workCalculator.getStartTime());
Date endDT = sdf.parse(workCalculator.getEndDate() " " workCalculator.getEndTime());
long timeDiffMilli = endDT.getTime() - startDT.getTime();
long timeDiffMin = TimeUnit.MILLISECONDS.toMinutes(timeDiffMilli) % 60;
long timeDiffH = TimeUnit.MILLISECONDS.toHours(timeDiffMilli) % 24;
workCalculator.setTotalWorkH(timeDiffH);
workCalculator.setTotalWorkMin(timeDiffMin);
workCalculatorService.save(workCalculator);
return "redirect:/index";
}
我的物體模型如下所示:
(...)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column(name = "start_date")
private String startDate;
@Column(name = "end_date")
private String endDate;
@Column(name = "total_work_h")
private long totalWorkH;
@Column(name = "total_work_min")
private long totalWorkMin;
@Column(name = "end_time")
private String endTime;
@Column(name = "start_time")
private String startTime;
(...)
我的資料庫架構看起來像:
(...)
CREATE TABLE `work_calc` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`start_date` varchar(30) DEFAULT NULL,
`end_date` varchar(30) DEFAULT NULL,
`start_time` varchar(20) DEFAULT NULL,
`end_time` varchar(20) DEFAULT NULL,
`total_work_h` int(10) DEFAULT NULL,
`total_work_min` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

提前感謝大家的努力和時間。
uj5u.com熱心網友回復:
時間
這很簡單。如果你只是允許它存在。我建議您對所有日期和時間作業使用 java.time,現代 Java 日期和時間 API。
// This should be your entity class
public class Work {
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm", Locale.ROOT);
private OffsetDateTime start;
private OffsetDateTime end;
public Work(OffsetDateTime start, OffsetDateTime end) {
this.start = start;
this.end = end;
}
public Duration getTotalWorkTime() {
return Duration.between(start, end);
}
@Override
public String toString() {
return start.format(FORMATTER) " - " end.format(FORMATTER);
}
}
讓我們試試看。為了構造一些Work物件,我撰寫了以下輔助方法。它接受日期和時間的字串。
/** Switzerland time */
private static final ZoneId ZONE = ZoneId.of("Europe/Zurich");
private static Work buildWork(String startDate, String startTime,
String endDate, String endTime) {
ZonedDateTime start = ZonedDateTime.of(
LocalDate.parse(startDate), LocalTime.parse(startTime), ZONE);
ZonedDateTime end = ZonedDateTime.of(
LocalDate.parse(endDate), LocalTime.parse(endTime), ZONE);
if (start.isAfter(end)) {
throw new IllegalArgumentException("Start must not be after end");
}
return new Work(start.toOffsetDateTime(), end.toOffsetDateTime());
}
示范:
Work[] exampleEntities = {
buildWork("2021-10-13", "07:00", "2021-10-14", "17:45"),
buildWork("2021-10-15", "07:00", "2021-10-15", "21:00"),
buildWork("2021-10-30", "21:00", "2021-10-31", "07:00")
};
for (Work work : exampleEntities) {
Duration totalWork = work.getTotalWorkTime();
System.out.format("%s: %-8s or - hours - minutes%n", work,
totalWork, totalWork.toHours(), totalWork.toMinutesPart());
}
輸出:
2021-10-13 07:00 - 2021-10-14 17:45: PT34H45M or 34 hours 45 minutes 2021-10-15 07:00 - 2021-10-15 21:00: PT14H or 14 hours 0 minutes 2021-10-30 21:00 - 2021-10-31 07:00: PT11H or 11 hours 0 minutes
In a normal night we would expect the time from 21:00 to 7:00 to be 10 hours. You can see in the above output that in the night between October 30 and 31, where Europe turns its clocks back after summer time (DST), it’s 11 hours. Edit: If one is in doubt, here’s a way to see it: The worker first works from 21 to 3 = 6 hours. Then the clocks are turned back to 2. The worker then continues working from 2 to 7 = 5 hours. So the total time worked i 6 5 hours = 11 hours. So the code calculates the actual time elapsed (not the difference between the clock hours).
Further points I wanted to make
- Use proper date-time objects for storing date and time. You don’t store numbers and Boolean values in strings (I sure hope), you also should not store dates and times in strings. I had really wanted to use
ZonedDateTimefor a date and time with a time zone (like Europe/Zurich), but many SQL databases cannot store the value of aZonedDateTimewith a real time zone, so we may have to useOffsetDateTimeas in the code above. AnOffsetDateTimefits nicely into atimestamp with time zonecolumn of common SQL databases, though variations between vendors are great. For an amount of time use theDurationclass in Java (not separate numbers). - Don’t store redundant information in your entity. The risk of some database update causing undetected data inconsistency is too great. Total work time can be calculated from start and end, so we simply calculate them on demand (which probably isn’t that often, but you know better).
- As MadProgrammer said in a comment, leave to the standard library methods to perform date and time math. It’s often more complicated than you think, so don’t do it by hand as in your own code.
Was your code reliable?
Giving just a partial answer to your question as asked. There isn’t much reliable about the old date and time classes from Java 1.0 and 1.1. Even if you get code to work with them, it will often be needlessly complicated code, and the risk of some fellow programmer introducing a bug later should not be overlooked.
I didn’t test your code with data from the nights of fall back (for example 30–31 October 2021) and spring forward (expected 26–27 March 2022). You can do that yourself.
You have got a very long work shift from 2021-10-13 07:00 to 2021-10-14 17:45. It may be an error in the data, but work time should be calculated correctly, which will also help the user notice if it is indeed an error. The correct duration is 34 hours 45 minutes. It seems from your screen shot that your code has calculated it as just 10 hours 45 minutes.
Link
Oracle tutorial: Date Time explaining how to use java.time.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/327969.html
