java.util.Date
Scala에서 Java 클래스를 사용 하고 있으며 Date
객체와 현재 시간 을 비교하고 싶습니다 . getTime ()을 사용하여 델타를 계산할 수 있다는 것을 알고 있습니다.
(new java.util.Date()).getTime() - oldDate.getTime()
그러나 이것은 단지 long
밀리 초를 나타냅니다. 시간 델타를 얻는 더 간단하고 좋은 방법이 있습니까?
답변
JDK Date
API는 불행히도 크게 망가졌습니다. Joda Time 라이브러리를 사용하는 것이 좋습니다 .
Joda Time에는 시간 간격 개념이 있습니다 .
Interval interval = new Interval(oldTime, new Instant());
편집 : 그런데, Joda는 두 Interval
시간 순간 사이의 시간 간격을 나타내는 개념 (8am과 10am 사이 Duration
의 시간을 나타냄 )과 실제 시간 경계가없는 시간을 나타내는 것 (예 : 2 시간을 나타냄)이라는 두 가지 개념을 가지고 있습니다.
시간 비교에만 관심이 있다면 대부분의 Date
구현 (JDK 포함) Comparable
은 사용자가 사용할 수있는 인터페이스를 구현 합니다.Comparable.compareTo()
답변
간단한 diff (lib없이)
/**
* Get a diff between two dates
* @param date1 the oldest date
* @param date2 the newest date
* @param timeUnit the unit in which you want the diff
* @return the diff value, in the provided unit
*/
public static long getDateDiff(Date date1, Date date2, TimeUnit timeUnit) {
long diffInMillies = date2.getTime() - date1.getTime();
return timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS);
}
그리고 당신은 전화 할 수 있습니다 :
getDateDiff(date1,date2,TimeUnit.MINUTES);
두 날짜의 차이를 분 단위로 가져옵니다.
TimeUnit
는 java.util.concurrent.TimeUnit
나노에서 며칠로가는 표준 Java 열거 형입니다.
사람이 읽을 수있는 diff (lib없이)
public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {
long diffInMillies = date2.getTime() - date1.getTime();
//create the list
List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
Collections.reverse(units);
//create the result map of TimeUnit and difference
Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
long milliesRest = diffInMillies;
for ( TimeUnit unit : units ) {
//calculate difference in millisecond
long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
long diffInMilliesForUnit = unit.toMillis(diff);
milliesRest = milliesRest - diffInMilliesForUnit;
//put the result in the map
result.put(unit,diff);
}
return result;
}
출력은 Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
단위가 주문 된 것과 같습니다 .
해당 맵을 사용자 친화적 인 문자열로 변환하면됩니다.
경고
위의 코드 스 니펫은 두 순간 사이의 간단한 차이를 계산합니다. 이 게시물 에서 설명한 것처럼 일광 절약 스위치 중에 문제가 발생할 수 있습니다 . 즉, 시간이없는 날짜 사이의 차이를 계산하면 날짜 / 시간이 누락 될 수 있습니다.
내 의견으로는 날짜 차이는 주관적이며 특히 며칠입니다. 당신은 할 수있다:
-
24 시간 경과 시간 계산 : day + 1-day = 1 day = 24h
-
일광 절약 시간을 돌보는 경과 시간 수를 세십시오 : day + 1-day = 1 = 24h (그러나 자정 시간과 일광 절약 시간을 사용하면 0 일과 23 시간이 될 수 있습니다)
-
수 집계
day switches
(: P 일광 절약이있는 경우 또는 1H), 경과 시간은 단지 2H 경우에도, 일 오전 11 = 1 일 – + 1 일 오후 1시 수단
일의 날짜 차이 정의가 첫 번째 사례와 일치하면 내 답변이 유효합니다.
JodaTime으로
JodaTime을 사용하는 경우 다음을 사용하여 2 개의 인스턴트 (millies 백업 ReadableInstant) 날짜에 대한 차이를 얻을 수 있습니다.
Interval interval = new Interval(oldInstant, new Instant());
그러나 현지 날짜 / 시간에 대한 차이점을 얻을 수도 있습니다.
// returns 4 because of the leap year of 366 days
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5), PeriodType.years()).getYears()
// this time it returns 5
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5+1), PeriodType.years()).getYears()
// And you can also use these static methods
Years.yearsBetween(LocalDate.now(), LocalDate.now().plusDays(365*5)).getYears()
답변
int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime())
/ (1000 * 60 * 60 * 24) )
이것은 UTC 날짜와 함께 작동하므로 현지 날짜를 보면 차이가 날 수 있습니다. 현지 날짜와 올바르게 작동하려면 일광 절약 시간으로 인해 완전히 다른 방법이 필요합니다.
답변
Java 8 이상에 내장 된 java.time 프레임 워크 사용 :
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println("ISO-8601: " + duration);
System.out.println("Minutes: " + duration.toMinutes());
산출:
ISO-8601 : PT24H10M
분 : 1450
자세한 내용은 Oracle Tutorial 및 ISO 8601 표준을 참조하십시오 .
답변
문제를보다 명확하게 정의해야합니다. 당신은 할 수 단지 둘 사이의 밀리 초 단위로 가지고 Date
예를 들어, 24 시간을 밀리 초 단위로 개체와 나누기 :하지만 …
- 시간대를 고려하지 않습니다-
Date
항상 UTC - 일광 절약 시간을 고려하지 않습니다 (예를 들어 23 시간 밖에 걸리지 않는 날이있을 수 있음)
- UTC 내에서도 8 월 16 일 오후 11 시부 터 8 월 18 일 오전 2 시까 지 며칠이 있습니까? 27 시간 밖에 안 남았나요? 아니면 3 개의 날짜를 다루므로 3 일이되어야합니까?
답변
tl; dr
사용하지 않는 java.util.Date
개체를 대체물로 변환하십시오 java.time.Instant
. 그런 다음 경과 시간을로 계산하십시오 Duration
.
Duration d =
Duration.between( // Calculate the span of time between two moments as a number of hours, minutes, and seconds.
myJavaUtilDate.toInstant() , // Convert legacy class to modern class by calling new method added to the old class.
Instant.now() // Capture the current moment in UTC. About two and a half hours later in this example.
)
;
d.toString () : PT2H34M56S
d.toMinutes () : 154
d.toMinutesPart () : 34
ISO 8601 형식 : PnYnMnDTnHnMnS
합리적인 표준 ISO 8601 은 시간 범위의 간결한 텍스트 표현을 몇 년, 월, 일, 시간 등으로 정의합니다. 표준은 그러한 기간을 기간 이라고 부릅니다 . 형식은 PnYnMnDTnHnMnS
를 Where P
수단 “기간”은이 T
시간 부분의 일 부분을 분리하고, 다음에 문자 숫자 사이.
예 :
P3Y6M4DT12H30M5S
3 년, 6 개월, 4 일, 12 시간, 30 분 및 5 초PT4H30M
4 시간 반
java.time
Java 8 이상에 내장 된 java.time 프레임 워크는 번거로운 이전 java.util.Date
/ java.util.Calendar
클래스를 대체합니다 . 새로운 클래스는 개념적으로 유사하지만 재구성 된 후계자로 의도 된 매우 성공적인 Joda-Time 프레임 워크에서 영감을 얻었습니다 . JSR 310에 의해 정의됩니다 . ThreeTen-Extra 프로젝트로 확장되었습니다 . 학습서를 참조하십시오 .
순간
이 Instant
클래스는 나노초 의 해상도 (소수점의 최대 9 자리)로 UTC 의 타임 라인에서 순간을 나타냅니다 .
Instant instant = Instant.now() ; // Capture current moment in UTC.
Date
/ 와 같은 레거시 클래스를 피하는 것이 가장 Calendar
좋습니다. 그러나 아직 java.time으로 업데이트되지 않은 이전 코드와 상호 운용해야하는 경우 앞뒤로 변환하십시오. 이전 클래스에 추가 된 새 변환 메소드를 호출하십시오. 에서로 이동 java.util.Date
하려면을 (를 Instant
) 호출하십시오 Date::toInstant
.
Instant instant = myJavaUtilDate.toInstant() ; // Convert from legacy `java.util.Date` class to modern `java.time.Instant` class.
시간의 경간
java.time 클래스는 시간 범위를 몇 년, 월, 일, 시간, 분, 초로 나타내는이 아이디어를 두 개의 반으로 나눕니다.
다음은 예입니다.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime future = now.plusMinutes ( 63 );
Duration duration = Duration.between ( now , future );
콘솔로 덤프하십시오.
모두 Period
와 Duration
사용 ISO 8601 의 가치의 String 표현을 생성하기위한 표준.
System.out.println ( "now: " + now + " to future: " + now + " = " + duration );
지금 : 2015-11-26T00 : 46 : 48.016-05 : 00 [미국 / 몬트리올]에서 미래로 : 2015-11-26T00 : 46 : 48.016-05 : 00 [미국 / 몬트리올] = PT1H3M
Java 9는 Duration
일 부분, 시간 부분, 분 부분 및 초 부분을 가져 오는 메소드를 추가합니다 .
전체 지속 시간에서 총 일 수, 시간 또는 분 또는 초 또는 밀리 초 또는 나노초를 얻을 수 있습니다.
long totalHours = duration.toHours();
Java 9에서 Duration
클래스는 일,시, 분, 초, 밀리 초 / 나노초의 다양한 부분을 반환 하기 위한 새로운 메소드 를 얻습니다 . , 등 의 to…Part
메소드를 호출하십시오 .toDaysPart()
toHoursPart()
ChronoUnit
“일수”와 같이 더 간단한 시간 단위 만 신경 쓰는 경우 ChronoUnit
열거 형을 사용하십시오 .
long daysElapsed = ChronoUnit.DAYS.between( earlier , later );
또 다른 예.
Instant now = Instant.now();
Instant later = now.plus( Duration.ofHours( 2 ) );
…
long minutesElapsed = ChronoUnit.MINUTES.between( now , later );
120
java.time에 대하여
java.time의 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이 클래스는 까다로운 기존에 대신 기존 과 같은 날짜 – 시간의 수업을 java.util.Date
, Calendar
, SimpleDateFormat
.
Joda 타임 프로젝트는 현재의 유지 관리 모드 , java.time로 마이그레이션을 조언한다.
자세한 내용은 Oracle Tutorial을 참조하십시오 . 많은 예제와 설명을 보려면 스택 오버플로를 검색하십시오. 사양은 JSR 310 입니다.
java.time 클래스는 어디서 구할 수 있습니까?
- 자바 SE 8 및 SE 9 이상
- 내장.
- 번들로 구현 된 표준 Java API의 일부입니다.
- Java 9에는 몇 가지 사소한 기능과 수정 사항이 추가되었습니다.
- Java SE 6 및 SE 7
- 대부분의 java.time 기능은 ThreeTen-Backport의 Java 6 & 7로 백 포트됩니다 .
- 기계적 인조 인간
- ThreeTenABP의 프로젝트 적응 ThreeTen – 백 포트 특히 안드로이드에 대한 (위에서 언급).
- 사용 방법…을 참조하십시오 .
ThreeTen – 추가 프로젝트 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 향후 java.time에 추가 될 수있는 입증 된 근거입니다. 당신은 여기에 몇 가지 유용한 클래스와 같은 찾을 수 있습니다 Interval
, YearWeek
, YearQuarter
, 그리고 더 .
조다 타임
업데이트 : Joda-Time 프로젝트는 이제 유지 관리 모드 에 있으며 팀은 java.time 으로의 마이그레이션을 조언합니다. 클래스 . 나는 역사를 위해이 섹션을 그대로 둡니다.
Joda-Time 라이브러리는 기본값으로 ISO 8601을 사용합니다. 이 Period
클래스는 이러한 PnYnMnDTnHnMnS 문자열을 구문 분석하고 생성합니다.
DateTime now = DateTime.now(); // Caveat: Ignoring the important issue of time zones.
Period period = new Period( now, now.plusHours( 4 ).plusMinutes( 30));
System.out.println( "period: " + period );
렌더 :
period: PT4H30M
답변
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();