Java 8: 여러 단위의 2개의 LocalDateTime 차이
는 두 사람의 하려고 한다.LocalDateTime
출력은 형식이어야 합니다.y years m months d days h hours m minutes s seconds
제가 쓴 글은 다음과 같습니다.
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.ZoneId;
public class Main {
static final int MINUTES_PER_HOUR = 60;
static final int SECONDS_PER_MINUTE = 60;
static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
public static void main(String[] args) {
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 9, 19, 46, 45);
LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);
Period period = getPeriod(fromDateTime, toDateTime);
long time[] = getTime(fromDateTime, toDateTime);
System.out.println(period.getYears() + " years " +
period.getMonths() + " months " +
period.getDays() + " days " +
time[0] + " hours " +
time[1] + " minutes " +
time[2] + " seconds.");
}
private static Period getPeriod(LocalDateTime dob, LocalDateTime now) {
return Period.between(dob.toLocalDate(), now.toLocalDate());
}
private static long[] getTime(LocalDateTime dob, LocalDateTime now) {
LocalDateTime today = LocalDateTime.of(now.getYear(),
now.getMonthValue(), now.getDayOfMonth(), dob.getHour(), dob.getMinute(), dob.getSecond());
Duration duration = Duration.between(today, now);
long seconds = duration.getSeconds();
long hours = seconds / SECONDS_PER_HOUR;
long minutes = ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
long secs = (seconds % SECONDS_PER_MINUTE);
return new long[]{hours, minutes, secs};
}
}
가 받고 있는 은 " " " " 입니다.29 years 8 months 24 days 12 hours 0 minutes 50 seconds
이 웹사이트에서 결과를 확인했습니다(값 포함).12/16/1984 07:45:55
★★★★★★★★★★★★★★★★★」09/09/2014 19:46:45
다음의 스크린샷은 출력을 나타내고 있습니다.
제 코드에서 month 값 뒤의 필드가 잘못되어 있는 것이 확실합니다.어떤 제안이라도 해주시면 감사하겠습니다.
갱신하다
다른 웹사이트에서 테스트한 결과 결과가 다릅니다.여기: 두 날짜 사이의 기간을 계산합니다(결과: 29년, 8개월, 24일, 12시간, 0분, 50초).
갱신하다
두 개의 다른 사이트에서 두 개의 다른 결과가 나왔기 때문에, 저는 제 계산 알고리즘이 적법한지 궁금합니다. 두 개를 LocalDateTime
★★★★★★★★★★★★★★★★★★:
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45);
LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);
에 '하다, 하다, 하다'라는 결과가 29 years 8 months 25 days -1 hours -5 minutes -10 seconds.
이 링크에서 다음과 같이 됩니다.29 years 8 months 24 days 22 hours, 54 minutes and 50 seconds
따라서 알고리즘은 음의 숫자도 처리해야 합니다.
문제는 어떤 사이트에서 어떤 결과를 얻었느냐가 아니라 올바른 알고리즘을 알고 올바른 결과를 얻어야 합니다.
Chrono Unit을 사용하는 것이 가장 좋은 방법이라고 생각합니다.
long minutes = ChronoUnit.MINUTES.between(fromDate, toDate);
long hours = ChronoUnit.HOURS.between(fromDate, toDate);
기타 매뉴얼은 https://docs.oracle.com/javase/tutorial/datetime/iso/period.html에서 보실 수 있습니다.
공교롭게도 기간제 수업은 없는 것 같기 때문에 스스로 계산해야 할 수도 있습니다.
다행히 날짜와 시간 클래스에는 그것을 어느 정도 단순화하는 많은 유틸리티 메서드가 있습니다.가장 빠를 필요는 없지만 차이를 계산하는 방법은 다음과 같습니다.
LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45);
LocalDateTime tempDateTime = LocalDateTime.from( fromDateTime );
long years = tempDateTime.until( toDateTime, ChronoUnit.YEARS );
tempDateTime = tempDateTime.plusYears( years );
long months = tempDateTime.until( toDateTime, ChronoUnit.MONTHS );
tempDateTime = tempDateTime.plusMonths( months );
long days = tempDateTime.until( toDateTime, ChronoUnit.DAYS );
tempDateTime = tempDateTime.plusDays( days );
long hours = tempDateTime.until( toDateTime, ChronoUnit.HOURS );
tempDateTime = tempDateTime.plusHours( hours );
long minutes = tempDateTime.until( toDateTime, ChronoUnit.MINUTES );
tempDateTime = tempDateTime.plusMinutes( minutes );
long seconds = tempDateTime.until( toDateTime, ChronoUnit.SECONDS );
System.out.println( years + " years " +
months + " months " +
days + " days " +
hours + " hours " +
minutes + " minutes " +
seconds + " seconds.");
//prints: 29 years 8 months 24 days 22 hours 54 minutes 50 seconds.
기본 개념은 다음과 같습니다. 임시 시작 날짜를 만들고 1년 내내 일을 마무리합니다.그런 다음 시작 날짜가 종료로부터 1년 미만이 되도록 해당 날짜를 년 수로 조정합니다.각 시간 단위로 내림차순으로 반복합니다.
마지막으로 면책사항:다른 시간대(둘 다 같은 시간대여야 함)를 고려하지 않았고, 서머타임이나 캘린더의 다른 변경(사모아의 시간대 변경 등)이 이 계산에 어떤 영향을 미치는지도 테스트/체크하지 않았습니다.그러니 조심해서 사용하세요.
좀 더 간단해야죠!
Duration.between(startLocalDateTime, endLocalDateTime).toMillis();
millis는 원하는 단위로 변환할 수 있습니다.
String.format("%d minutes %d seconds",
TimeUnit.MILLISECONDS.toMinutes(millis),
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
다음 예제에서는 Duration 및 TimeUnit을 사용하여 'hh:mm:ss' 형식을 가져옵니다.
Duration dur = Duration.between(localDateTimeIni, localDateTimeEnd);
long millis = dur.toMillis();
String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
TL;DR
// get the calendar period between the times (years, months & days)
Period period = Period.between(start.toLocalDate(), end.toLocalDate());
// make sure to get the floor of the number of days
period = period.minusDays(end.toLocalTime().compareTo(start.toLocalTime()) >= 0 ? 0 : 1);
// get the remainder as a duration (hours, minutes, etc.)
Duration duration = Duration.between(start, end);
// remove days, already counted in the period
duration = duration.minusDays(duration.toDaysPart());
다음 '다 하다'라는 하세요.period.getYears()
,period.getMonths()
,period.getDays()
,duration.toHoursPart()
,duration.toMinutesPart()
,duration.toSecondsPart()
.
답변 확대
두 수 LocalDateTimes
의 "합" (총 , 각 으로 큰 ", ", ", ")보다 작도록 .minutes < 60
,hours < 24
기타 등등.
지정 시 2개 지정LocalDateTimes
start
★★★★★★★★★★★★★★★★★」end
LocalDateTime start = LocalDateTime.of(2019, 11, 28, 17, 15);
LocalDateTime end = LocalDateTime.of(2020, 11, 30, 16, 44);
둘 를 a로 수 .Duration
를 사용한 : """Duration.between(start, end)
우리가 할 수 큰 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★Duration
는 일수(24시간에 상당하는 시간 단위)입니다.설명에 대해서는, 다음의 주를 참조해 주세요.큰 단위 년)로.Duration
)로) 한 Period
,Duration
「」, 「」, 「 。Period
는 일 와 일 단위 및 일 단위까지의 Duration
나머지를 나타냅니다.
「 」를 Period
:
Period period = Period.between(start.toLocalDate(), end.toLocalDate());
요. '우리'는 '우리'는 '우리'가 아니라 '우리'는 '우리'가 아니라 '우리'가 아니라 '우리'가 아니라 '우리'가 아니라 '우리'가 아니라 '우리'가'Period
는 실제 날짜의 차이이지 시간의 양이 아닙니다.모든 계산은 달력 날짜를 기준으로 합니다(아래 항 참조).예를 들어 2000년 1월1일 23시 59분부터 2000년1월 2일 00시 1분까지Period
시간 차이가 24시간 미만인 경우에도 두 날짜의 차이가 1일이라고 할 수 있습니다.따라서 종료 날짜의 시각이 시작 날짜의 시각보다 빠를 경우, 24시간의 완전한 스팬에 대응하지 않기 때문에 일수에서 1을 빼야 합니다(나머지는 다음 시간에 의해 기록됩니다).Duration
period = period.minusDays(end.toLocalTime().compareTo(start.toLocalTime()) >= 0 ? 0 : 1);
하려면 , 「지지 a a a a a a a a」로서Duration
:
Duration duration = Duration.between(start, end);
일 단위까지의 차이는 이미 주기별로 처리되어 있기 때문에 더 작은 단위(시간, 분 등)만 유지하면 됩니다.
duration = duration.minusDays(duration.toDaysPart()); // essentially "duration (mod 1 day)"
이번에는 '아까부터'에서 할 수 .Period
★★★★★★★★★★★★★★★★★」Duration
「 」 、 「 」 、 「 」:
System.out.printf(
"%d years, %d months, %d days, %d hours, %d minutes, %d seconds",
period.getYears(), period.getMonths(), period.getDays(),
duration.toHoursPart(), duration.toMinutesPart(), duration.toSecondsPart()
);
1 years, 0 months, 1 days, 23 hours, 29 minutes, 0 seconds
또는 기본 형식을 사용하여 다음을 수행합니다.
System.out.println(period + " + " + duration);
P1Y1D + PT23H29M
년, 월, 일수에 대한 메모
해 주세요.java.time
의 "년과 같은 합니다.다음 예시와 같이 날짜 및 달력에 의존합니다.
LocalDateTime
start1 = LocalDateTime.of(2020, 1, 1, 0, 0),
end1 = LocalDateTime.of(2021, 1, 1, 0, 0),
start2 = LocalDateTime.of(2021, 1, 1, 0, 0),
end2 = LocalDateTime.of(2022, 1, 1, 0, 0);
System.out.println(Period.between(start1.toLocalDate(), end1.toLocalDate()));
System.out.println(Duration.between(start1, end1).toDays());
System.out.println(Period.between(start2.toLocalDate(), end2.toLocalDate()));
System.out.println(Duration.between(start2, end2).toDays());
P1Y
366
P1Y
365
예로서 23:까지 a "da" "2000" "1" "23:59" "1" "2" 00:01" 입니다.Period
시간 차이가 24시간 미만인 경우에도 두 날짜의 차이가 1일이라고 할 수 있습니다.
여기 당신의 질문에 대한 매우 간단한 답이 있습니다.그건 효과가 있다.
import java.time.*;
import java.util.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
public class MyClass {
public static void main(String args[]) {
DateTimeFormatter T = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
Scanner h = new Scanner(System.in);
System.out.print("Enter date of birth[dd/mm/yyyy hh:mm]: ");
String b = h.nextLine();
LocalDateTime bd = LocalDateTime.parse(b,T);
LocalDateTime cd = LocalDateTime.now();
long minutes = ChronoUnit.MINUTES.between(bd, cd);
long hours = ChronoUnit.HOURS.between(bd, cd);
System.out.print("Age is: "+hours+ " hours, or " +minutes+ " minutes old");
}
}
Groovy의 @Thomas 버전은 값을 하드코딩하지 않고 목록에서 원하는 단위를 가져옵니다.이 구현(Java에 쉽게 포팅할 수 있음 - 함수 선언을 명시적으로 함)은 Thomas의 접근 방식을 더 재사용하기 쉽게 만듭니다.
def fromDateTime = LocalDateTime.of(1968, 6, 14, 0, 13, 0)
def toDateTime = LocalDateTime.now()
def listOfUnits = [
ChronoUnit.YEARS, ChronoUnit.MONTHS, ChronoUnit.DAYS,
ChronoUnit.HOURS, ChronoUnit.MINUTES, ChronoUnit.SECONDS,
ChronoUnit.MILLIS]
println calcDurationInTextualForm(listOfUnits, fromDateTime, toDateTime)
String calcDurationInTextualForm(List<ChronoUnit> listOfUnits, LocalDateTime ts, LocalDateTime to)
{
def result = []
listOfUnits.each { chronoUnit ->
long amount = ts.until(to, chronoUnit)
ts = ts.plus(amount, chronoUnit)
if (amount) {
result << "$amount ${chronoUnit.toString()}"
}
}
result.join(', ')
}
쓸 때 가 반환됩니다.47 Years, 8 Months, 9 Days, 22 Hours, 52 Minutes, 7 Seconds, 140 Millis
@Genady Kolomoets를 반환합니다.23 Hours
.
장치 목록을 제공하는 경우 장치 크기별로 정렬해야 합니다(가장 큰 항목 먼저).
def listOfUnits = [ChronoUnit.WEEKS, ChronoUnit.DAYS, ChronoUnit.HOURS]
// returns 2495 Weeks, 3 Days, 8 Hours
Tapas Bose 코드와 Thomas 코드에 문제가 있습니다.시차값이 음수인 경우 배열은 음수 값을 가져옵니다.예를 들어,
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 46, 45);
LocalDateTime fromDateTime = LocalDateTime.of(2014, 9, 9, 7, 46, 45);
0년 0개월 1일 -1시간 0분 0초를 반환합니다.
올바른 출력은 0년 0개월 0일 23시간 0분 0초입니다.
LocalDate 인스턴스와 LocalTime 인스턴스의 LocalDateTime 인스턴스를 분리할 것을 권장합니다.그 후 Java 8 Period 및 Duration 인스턴스를 얻을 수 있습니다.[ Duration ]인스턴스는 일수와 시간 값(< 24h)으로 구분되며 이후 기간 값이 수정됩니다.두 번째 LocalTime 값이 첫 번째 LocalTime 값보다 이전일 경우 하루의 기간을 줄여야 합니다.
LocalDateTime 차이를 계산하는 방법은 다음과 같습니다.
private void getChronoUnitForSecondAfterFirst(LocalDateTime firstLocalDateTime, LocalDateTime secondLocalDateTime, long[] chronoUnits) {
/*Separate LocaldateTime on LocalDate and LocalTime*/
LocalDate firstLocalDate = firstLocalDateTime.toLocalDate();
LocalTime firstLocalTime = firstLocalDateTime.toLocalTime();
LocalDate secondLocalDate = secondLocalDateTime.toLocalDate();
LocalTime secondLocalTime = secondLocalDateTime.toLocalTime();
/*Calculate the time difference*/
Duration duration = Duration.between(firstLocalDateTime, secondLocalDateTime);
long durationDays = duration.toDays();
Duration throughoutTheDayDuration = duration.minusDays(durationDays);
Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
"Duration is: " + duration + " this is " + durationDays
+ " days and " + throughoutTheDayDuration + " time.");
Period period = Period.between(firstLocalDate, secondLocalDate);
/*Correct the date difference*/
if (secondLocalTime.isBefore(firstLocalTime)) {
period = period.minusDays(1);
Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
"minus 1 day");
}
Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
"Period between " + firstLocalDateTime + " and "
+ secondLocalDateTime + " is: " + period + " and duration is: "
+ throughoutTheDayDuration
+ "\n-----------------------------------------------------------------");
/*Calculate chrono unit values and write it in array*/
chronoUnits[0] = period.getYears();
chronoUnits[1] = period.getMonths();
chronoUnits[2] = period.getDays();
chronoUnits[3] = throughoutTheDayDuration.toHours();
chronoUnits[4] = throughoutTheDayDuration.toMinutes() % 60;
chronoUnits[5] = throughoutTheDayDuration.getSeconds() % 60;
}
위의 방법을 사용하여 로컬 날짜 및 시간 값의 차이를 계산할 수 있습니다.다음은 예를 제시하겠습니다.
public long[] getChronoUnits(String firstLocalDateTimeString, String secondLocalDateTimeString) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime firstLocalDateTime = LocalDateTime.parse(firstLocalDateTimeString, formatter);
LocalDateTime secondLocalDateTime = LocalDateTime.parse(secondLocalDateTimeString, formatter);
long[] chronoUnits = new long[6];
if (secondLocalDateTime.isAfter(firstLocalDateTime)) {
getChronoUnitForSecondAfterFirst(firstLocalDateTime, secondLocalDateTime, chronoUnits);
} else {
getChronoUnitForSecondAfterFirst(secondLocalDateTime, firstLocalDateTime, chronoUnits);
}
return chronoUnits;
}
위의 방법에 대해 단위 테스트를 작성하는 것이 편리합니다(둘 다 PeriodDuration 클래스 멤버).코드는 다음과 같습니다.
@RunWith(Parameterized.class)
public class PeriodDurationTest {
private final String firstLocalDateTimeString;
private final String secondLocalDateTimeString;
private final long[] chronoUnits;
public PeriodDurationTest(String firstLocalDateTimeString, String secondLocalDateTimeString, long[] chronoUnits) {
this.firstLocalDateTimeString = firstLocalDateTimeString;
this.secondLocalDateTimeString = secondLocalDateTimeString;
this.chronoUnits = chronoUnits;
}
@Parameters
public static Collection<Object[]> periodValues() {
long[] chronoUnits0 = {0, 0, 0, 0, 0, 0};
long[] chronoUnits1 = {0, 0, 0, 1, 0, 0};
long[] chronoUnits2 = {0, 0, 0, 23, 0, 0};
long[] chronoUnits3 = {0, 0, 0, 1, 0, 0};
long[] chronoUnits4 = {0, 0, 0, 23, 0, 0};
long[] chronoUnits5 = {0, 0, 1, 23, 0, 0};
long[] chronoUnits6 = {29, 8, 24, 12, 0, 50};
long[] chronoUnits7 = {29, 8, 24, 12, 0, 50};
return Arrays.asList(new Object[][]{
{"2015-09-09 21:46:44", "2015-09-09 21:46:44", chronoUnits0},
{"2015-09-09 21:46:44", "2015-09-09 22:46:44", chronoUnits1},
{"2015-09-09 21:46:44", "2015-09-10 20:46:44", chronoUnits2},
{"2015-09-09 21:46:44", "2015-09-09 20:46:44", chronoUnits3},
{"2015-09-10 20:46:44", "2015-09-09 21:46:44", chronoUnits4},
{"2015-09-11 20:46:44", "2015-09-09 21:46:44", chronoUnits5},
{"1984-12-16 07:45:55", "2014-09-09 19:46:45", chronoUnits6},
{"2014-09-09 19:46:45", "1984-12-16 07:45:55", chronoUnits6}
});
}
@Test
public void testGetChronoUnits() {
PeriodDuration instance = new PeriodDuration();
long[] expResult = this.chronoUnits;
long[] result = instance.getChronoUnits(this.firstLocalDateTimeString, this.secondLocalDateTimeString);
assertArrayEquals(expResult, result);
}
}
첫 번째 LocalDateTime 값이 LocalTime 값 이전인지 여부에 관계없이 모든 테스트가 성공합니다.
5년 이상 후에 나는 내 질문에 대답한다.음의 지속시간을 갖는 문제는 간단한 보정으로 해결할 수 있다고 생각합니다.
LocalDateTime fromDateTime = LocalDateTime.of(2014, 9, 9, 7, 46, 45);
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 46, 45);
Period period = Period.between(fromDateTime.toLocalDate(), toDateTime.toLocalDate());
Duration duration = Duration.between(fromDateTime.toLocalTime(), toDateTime.toLocalTime());
if (duration.isNegative()) {
period = period.minusDays(1);
duration = duration.plusDays(1);
}
long seconds = duration.getSeconds();
long hours = seconds / SECONDS_PER_HOUR;
long minutes = ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
long secs = (seconds % SECONDS_PER_MINUTE);
long time[] = {hours, minutes, secs};
System.out.println(period.getYears() + " years "
+ period.getMonths() + " months "
+ period.getDays() + " days "
+ time[0] + " hours "
+ time[1] + " minutes "
+ time[2] + " seconds.");
주의: 사이트 https://www.epochconverter.com/date-difference에서 시차를 올바르게 계산하게 되었습니다.
여러분의 논의와 제안에 감사드립니다.
조다 타임
API 26 지원이 필요한 답변이 많고 최소 API가 23이었기 때문에 아래 코드로 해결했습니다.
import org.joda.time.Days
LocalDate startDate = Something
LocalDate endDate = Something
// The difference would be exclusive of both dates,
// so in most of use cases we may need to increment it by 1
Days.daysBetween(startDate, endDate).days
언급URL : https://stackoverflow.com/questions/25747499/java-8-difference-between-two-localdatetime-in-multiple-units
'source' 카테고리의 다른 글
Java에서 Base64로 인코딩 (0) | 2022.08.16 |
---|---|
값(vuej)을 전달하시겠습니까? (0) | 2022.08.16 |
Vuex가 정의되지 않은 속성을 읽을 수 없음 (0) | 2022.08.16 |
vuex-store에서 vue child-component를 업데이트하려면 어떻게 해야 합니까? (0) | 2022.08.16 |
Java에서 HTTP GET을 실행하려면 어떻게 해야 하나요? (0) | 2022.08.16 |