오늘의 잔디
오늘의 공부
"Asia/Seoul" 같은 타임존 안에는 일광 절약 시간제에 대한 정보와 UTC+9:00와 같은 UTC로 부터 시간 차이인 오프셋 정보를 모두 포함하고 있다.
타임존 목록 예시
자바는 타임존을 ZoneId 클래스로 제공한다.
package time;
import java.time.ZoneId;public class ZoneIdMain {
public static void main(String[] args) {
for (String availableZoneId : ZoneId.getAvailableZoneIds()) {
ZoneId zoneId = ZoneId.of(availableZoneId);
System.out.println(zoneId + " | " + zoneId.getRules());
}
ZoneId zoneId = ZoneId.systemDefault();
System.out.println("ZoneId.systemDefault = " + zoneId);
ZoneId seoulZoneId = ZoneId.of("Asia/Seoul");
System.out.println("seoulZoneId = " + seoulZoneId);
}
}
실행 결과
Europe/London | ZoneRules[currentStandardOffset=Z]
UTC | ZoneRules[currentStandardOffset=Z]
GMT | ZoneRules[currentStandardOffset=Z]
Asia/Seoul | ZoneRules[currentStandardOffset=+09:00]
Asia/Dubai | ZoneRules[currentStandardOffset=+04:00]
US/Arizona | ZoneRules[currentStandardOffset=-07:00]
Asia/Istanbul | ZoneRules[currentStandardOffset=+03:00]
Asia/Shanghai | ZoneRules[currentStandardOffset=+08:00]
...
Europe/Paris | ZoneRules[currentStandardOffset=+01:00]
ZoneId.systemDefault = Asia/Seoul
seoulZoneId = Asia/Seoul
생성
ZoneId.systemDefault() : 시스템이 사용하는 기본 ZoneId 를 반환한다.ZoneId.of() : 타임존을 직접 제공해서 ZoneId 를 반환한다.ZoneId 는 내부에 일광 절약 시간 관련 정보, UTC와의 오프셋 정보를 포함하고 있다.
ZonedDateTime 은 LocalDateTime 에 시간대 정보인 ZoneId 가 합쳐진 것이다.
ZonedDateTime 클래스
public class ZonedDateTime {
private final LocalDateTime dateTime;
private final ZoneOffset offset;
private final ZoneId zone;
}
ZonedDateTime: 시간대를 고려한 날짜와 시간을 표현할 때 사용한다. 여기에는 시간대를 표현하는 타임존이 포함된
다.
2013-11-21T08:20:30.213+9:00[Asia/Seoul]+9:00 은 UTC(협정 세계시)로 부터의 시간대 차이이다. 오프셋이라 한다. 한국은 UTC보다 +9:00 시간이다.Asia/Seoul 은 타임존이라고 한다. 이 타임존을 알면 오프셋도 알 수 있다. +9:00 같은 오프셋 정보도 타임존에 포함된다. ZoneId 를 통해 타임존을 알면 일광 절약 시간제에 대한 정보도 알 수 있다. 따라서 일광 절약 시간제가package time;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class ZonedDateTimeMain {
public static void main(String[] args) {
ZonedDateTime nowZdt = ZonedDateTime.now();
System.out.println("nowZdt = " + nowZdt);
LocalDateTime ldt = LocalDateTime.of(2030, 1, 1, 13, 30, 50);
ZonedDateTime zdt1 = ZonedDateTime.of(ldt, ZoneId.of("Asia/Seoul"));
System.out.println("zdt1 = " + zdt1);
ZonedDateTime zdt2 = ZonedDateTime.of(2030, 1, 1, 13, 30, 50, 0, ZoneId.of("Asia/Seoul"));
System.out.println("zdt2 = " + zdt2);
ZonedDateTime utcZdt = zdt2.withZoneSameInstant(ZoneId.of("UTC"));
System.out.println("utcZdt = " + utcZdt);
}
}
실행 결과
nowZdt = 2024-02-09T12:02:13.457712+09:00[Asia/Seoul]
zdt1 = 2030-01-01T13:30:50+09:00[Asia/Seoul]
zdt2 = 2030-01-01T13:30:50+09:00[Asia/Seoul]
utcZdt = 2030-01-01T04:30:50Z[UTC]
생성
now() : 현재 날짜와 시간을 기준으로 생성한다. 이때 ZoneId 는 현재 시스템을 따른다.ZoneId.systemDefault() )of(...) : 특정 날짜와 시간을 기준으로 생성한다. ZoneId 를 추가해야 한다.LocalDateTime 에 ZoneId 를 추가해서 생성할 수 있다.타임존 변경
withZoneSameInstant(ZoneId) : 타임존을 변경한다. 타임존에 맞추어 시간도 함께 변경된다. 이 메서드를 사용하면 지금 다른 나라는 몇 시 인지 확인일 수 있다. 예를 들어서 서울이 지금 9시라면, UTC 타임존으로 변경하면 0시를 확인할 수 있다.OffsetDateTime 은 LocalDateTime 에 UTC 오프셋 정보인 ZoneOffset 이 합쳐진 것이다.
OffsetDateTime 클래스
public class OffsetDateTime {
private final LocalDateTime dateTime;
private final ZoneOffset offset;
}
OffsetDateTime: 시간대를 고려한 날짜와 시간을 표현할 때 사용한다. 여기에는 타임존은 없고, UTC로 부터의 시간대 차이인 고정된 오프셋만 포함한다.
2013-11-21T08:20:30.213+9:00ZoneId 가 없으므로 일광 절약 시간제가 적용되지 않는다.package time;
import java.time.*;
public class OffsetDateTimeMain {
public static void main(String[] args) {
OffsetDateTime nowOdt = OffsetDateTime.now();
System.out.println("nowOdt = " + nowOdt);
LocalDateTime ldt = LocalDateTime.of(2030, 1, 1, 13, 30, 50);
System.out.println("ldt = " + ldt);
OffsetDateTime odt = OffsetDateTime.of(ldt, ZoneOffset.of("+01:00"));
System.out.println("odt = " + odt);
}
}
실행 결과
nowOdt = 2024-02-13T15:03:36.422230+09:00
ldt = 2030-01-01T13:30:50
odt = 2030-01-01T13:30:50+01:00
ZoneOffset 은 +01:00 처럼 UTC와의 시간 차이인 오프셋 정보만 보관한다.
ZonedDateTime vs OffsetDateTime
ZonedDateTime 은 구체적인 지역 시간대를 다룰 때 사용하며, 일광 절약 시간을 자동으로 처리할 수 있다. 사용자 지정 시간대에 따른 시간 계산이 필요할 때 적합하다.OffsetDateTime 은 UTC와의 시간 차이만을 나타낼 때 사용하며, 지역 시간대의 복잡성을 고려하지 않는다.참고
ZonedDateTime 이나 OffsetDateTime 은 글로벌 서비스를 하지 않으면 잘 사용하지 않는다. 따라서 너무 깊이있게 파기 보다는 대략 이런 것이 있다 정도로만 알아두면 된다. 실무에서 개발하면서 글로벌 서비스를 개발할 기회가 있다면 그때 필요한 부분을 찾아서 깊이있게 학습하면 된다.
Instant 는 UTC(협정 세계시)를 기준으로 하는, 시간의 한 지점을 나타낸다. Instant 는 날짜와 시간을 나노초 정밀도로 표현하며, 1970년 1월 1일 0시 0분 0초(UTC 기준)를 기준으로 경과한 시간으로 계산된다.
쉽게 이야기해서 Instant 내부에는 초 데이터만 들어있다. (나노초 포함)
따라서 날짜와 시간을 계산에 사용할 때는 적합하지 않다.
Instant 클래스
public class Instant {
private final long seconds;
private final int nanos;
...
}
seconds 에 0이 들어간다.seconds 에 10이 들어간다.seconds 에 60이 들어간다.참고 - Epoch 시간
Epoch time(에포크 시간), 또는 Unix timestamp는 컴퓨터 시스템에서 시간을 나타내는 방법 중 하나이다. 이는
1970년 1월 1일 00:00:00 UTC부터 현재까지 경과된 시간을 초 단위로 표현한 것이다. 즉, Unix 시간은 1970년 1월
1일 이후로 경과한 전체 초의 수로, 시간대에 영향을 받지 않는 절대적인 시간 표현 방식이다.
참고로 Epoch라는 뜻은 어떤 중요한 사건이 발생한 시점을 기준으로 삼는 시작점을 뜻하는 용어다.
Instant 는 바로 이 Epoch 시간을 다루는 클래스이다.
Instant 특징
Instant 는 UTC를 기준으로 하므로, 시간대에 영향을 받지 않는다. 이는 전 세계 어디서나 동일한 시점을 가리키는데 유용하다.Instant 는 1970년 1월 1일 UTC를 기준으로 하기 때문에, 시간 계산 및 비교가 명확하고 일관된다.Instant 는 기계적인 시간 처리에는 적합하지만, 사람이 읽고 이해하기에는 직Instant 에는 시간대 정보가 포함되어 있지 않아, 특정 지역의 날짜와 시간으로 변환하려면 추가적인 작업이 필요하다.사용 예
Instant 는 UTC를 기준으로 하므로, 전 세계적으로 일관된 시점을 표현할 때Instant 가 적합하다. 이는 시간대 변환의 복잡성 없이 시간 계산을 할 수 있게 해준다.Instant 를 사용하면, 모든 시스템에서 동일한 기준점(UTC)을 사용하게 되므로 데이터의 일관성을 유지하기 쉽다.일반적으로 날짜와 시간을 사용할 때는 LocalDateTime , ZonedDateTime 등을 사용하면 된다. Instant 는 날짜를 계산하기 어렵기 때문에 앞서 사용 예와 같은 특별한 경우에 한정해서 사용하면 된다.
package time;
import java.time.Instant;
import java.time.ZonedDateTime;
public class InstantMain {
public static void main(String[] args) {
//생성
Instant now = Instant.now(); //UTC 기준
System.out.println("now = " + now);
ZonedDateTime zdt = ZonedDateTime.now();
Instant from = Instant.from(zdt);
System.out.println("from = " + from);
Instant epochStart = Instant.ofEpochSecond(0); System.out.println("epochStart = " + epochStart);
//계산
Instant later = epochStart.plusSeconds(3600);
System.out.println("later = " + later);
//조회
long laterEpochSecond = later.getEpochSecond();
System.out.println("laterEpochSecond = " + laterEpochSecond);
}
}
실행 결과
now = 2024-02-13T06:46:07.101393Z
from = 2024-02-13T06:46:07.117732Z
epochStart = 1970-01-01T00:00:00Z
later = 1970-01-01T01:00:00Z
laterEpochSecond = 3600
생성
now() : UTC를 기준 현재 시간의 Instant 를 생성한다.from() : 다른 타입의 날짜와 시간을 기준으로 Instant 를 생성한다. 참고로 Instant 는 UTC를 기준으로 하기 때문에 시간대 정보가 필요하다. 따라서 LocalDateTime 은 사용할 수 없다.ofEpochSecond() : 에포크 시간을 기준으로 Instant 를 생성한다. 0초를 선택하면 에포크 시간인 1970년 1월 1일 0시 0분 0초로 생성된다.계산
plusSeconds() : 초를 더한다. 초, 밀리초, 나노초 정도만 더하는 간단한 메서드가 제공된다.조회
getEpochSecond() : 에포크 시간인 UTC 1970년 1월 1일 0시 0분 0초를 기준으로 흐른 초를 반환한다.Instant 정리
Instant , 미국에 있는Instant 의 시간이 똑같음epoch 시간 기반 계산이 필요할 때, 간단히 두 시간의 차이를 구할 때LocalDateTime 또는, ZonedDateTime 사용