# Date์ Time
# 1. Date์ Time ์๊ฐ
๋ ์ง์ ์๊ฐ์ ํํํ๊ธฐ ์ํด Java์์ ์ฌ์ฉํด์๋ค.
# 1-1. Java8์ ์๋ก์ด ๋ ์ง์ ์๊ฐ API๊ฐ ๋ฑ์ฅํ ์ด์
Date date = new Date();
Calendar calendar = new GregorianCalendar();
SimpleDateFormat dateFormat = new SimpleDateFormat();
Java 8 ์ด์ ์ฌ์ฉ๋๋ ๋ ์ง์ ์๊ฐ API๋ Date
์ Calendar
, GregorianCalendar
๋ฑ์ด ์์.
์ด๋ ๊ฒ ๊ธฐ์กด์ ์กด์ฌํ๋ API๋ค์ ๋ฌธ์ ์ ์ด ์์๋๋ฐ ํ๋์ฉ ์ดํด๋ณด์.
ํด๋์ค ์ด๋ฆ์ด ๋ช ํํ์ง๊ฐ ์๋ค.
- ๋ ์ง ํด๋์ค์ค
Date
๋์๊ฐ
๊ณผTimeStamp
๋ชจ๋ ํํํ ์ ์๋ค. (์ฌ์ค์TimeStamp
) - ์๊ฐ ๊ฐ์ด
์ํญ์
์ด๋ผ ํ์ฌ ์ธ๊ณ ํ์ค์(UTC)๋ก 1970๋ 1์ 1์ผ 00์ 00๋ถ 00์ด๋ฅผ ๊ธฐ์ค์ผ๋ก ํ์ฌ๊น์ง ํ๋ฅธ ๋ชจ๋ ์๊ฐ์ ์ด(sec)๋จ์๋ก ํํ (์ฌ๋์ด ์์๋ณด๊ธฐ ์ด๋ ค์)
- ๋ ์ง ํด๋์ค์ค
Mutable ํ์ฌ thread safeํ์ง ์๋ค.
public static void main(String[] args) throws InterruptedException { Date date = new Date(); long time = date.getTime(); System.out.println("date = " + date); Thread.sleep(1000 * 3); Date after3Seconds = new Date(); System.out.println("after3Seconds = " + after3Seconds); after3Seconds.setTime(time); System.out.println("after3Seconds = " + after3Seconds); } /* [์คํ ๊ฒฐ๊ณผ] date = Thu Oct 28 20:22:24 KST 2021 after3Seconds = Thu Oct 28 20:22:27 KST 2021 after3Seconds = Thu Oct 28 20:22:24 KST 2021 */
- ์ต์ด ์ฝ๋ ์คํ์ ์๊ฐ์ ์ถ๋ ฅ ํ 3์ด ํ์ ๋ค์ Date ์ธ์คํด์ค๋ฅผ ์์ฑํด ์ถ๋ ฅํ๋ค.
- ๊ทธ ๋ค์
setTime(time)
์ผ๋ก ์ต์ด ์์ฑํdate
๋ฅผ ์๋ก ์์ฑํafter3Seconds
์ set ํด ์ค๋ค ์ถ๋ ฅํ๋ ์ต์ด์ ์์ฑํ์ ๋น์์ ์๊ฐ์ด ์ถ๋ ฅ๋๋ค. - ์ด๋ Date ํด๋์ค๊ฐ
mutable
ํ๋ค๋ ๊ฒ์ ์๋ฏธ thread unsafe
: Date ์ธ์คํด์ค์ ๊ฐ์ ๊ฐ๊ฐ ๋ค๋ฅธ Thread์์ ์ ๊ทผํด์ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ฉด ๊ธฐ์กด์ ์ฌ์ฉํ๋ Thread์์ ๋ณ๊ฒฝ ๋์ด ์๋ชป๋ Date ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ํ์ด ์๋ค๋ ๋ป.
๋ฒ๊ทธ ๋ฐ์ํ ์ฌ์ง๊ฐ ๋ง๋ค.
- Thread unsafe ํ ๋ฟ ์๋๋ผ ์ฌ์ฉ๋ฒ ์์ฒด์์๋ ์ฌ์ฉ๋ฒ์ ๋ํด ์คํดํ ์ ์์ด ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ฌ์ง๊ฐ ์๋ค.
Calendar birthDay = new GregorianCalendar(1988, 6, 10);
- ์์ผ์ด 1988๋ 6์ 10์ผ์์ ํํํ๊ณ ์ถ์ง๋ง, GregorianCalendar์์ month๋ 0๋ถํฐ์์ํ๊ธฐ ๋๋ฌธ์ 6์ ๋ฃ์ผ๋ฉด 7์์ด๋ผ๋ ์๋ฏธ๊ฐ ๋๋ค.
- ํผ๋ํ์ง ์๊ธฐ ์ํด์ ์์ ๊ฐ์ ์ฐ๊ณค ํ๋ค.
(ex: Calendar.JUNE)
๊ทธ๋์ Java 8 ์ด์ ์๋ Joda-Time (opens new window) ์ ์ฌ์ฉํ๋ค.
# 1-2. Java ๋ ์ง ๋ฐ ์๊ฐ API๊ฐ ๊ฐ์ ธ์ผํ ๋์์ธ ์ฒ ํ
Clear
- API ๋ฉ์๋๋ ๋ช ํํด์ผํ๋ค.
- ์๋ฅผ๋ค์ด ํด๋์ค๋ช
์ด
Date
์ง๋ง ๋ ์ง ๋ฟ ์๋๋ผ ์๊ฐ(Time
)๊น์ง ๋ค๋ฃจ๊ฒ๋๋ฉด ๋ช ํํ์ง ์๋ค. - ๋ํ์ฌ ์๊ฐ(
Time
)์ญ์ ์ฌ๋์๊ฒ ์ต์ํ ์ผ๋ฐ ์๊ฐ์ด ์๋ ์ํญํ์์ธ ๊ฒ์Clear
ํ์ง ์๋ค.
Fluent
- ๋ฉ์๋๊ฐ null์ ๋ฐํํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋ฉ์๋ ์ฒด์ด๋์ด ๊ฐ๋ฅํ๊ธฐ์ ์ฝ๋๊ฐ ์ ๋ คํด์ง๋ค.
Immutable
- ๊ธฐ์กด ๋ ์ง ์ธ์คํด์ค์ ๋ด์ฉ์ด ๋ณํ์ง ์์ผ๋ฉฐ ๋ณ๊ฒฝ๋ฉ์๋ ํธ์ถ์ ๊ฐ์ด ๋ณ๊ฒฝ๋๋๊ฒ ์๋๋ผ ์๋ก์ด ๋ ์ง ์ธ์คํด์ค๋ฅผ ์์ฑํด ๋ฐํํด์ผํ๋ค.
LocalDate today = LocalDate.of(2021, Month.OCTOBER, 28); LocalDate nextMonth = today.plusMonths(1);
Extensible
- ํ์ฅ ๊ฐ๋ฅํด์ผ ํ๋ค.
- ๋ฌ๋ ฅ์๋ ์ค๋ฌ, ์๋ ฅ, ์๋ ฅ, ๋ถ๊ต๋ฌ๋ ฅ ๋ฑ ๋ค์ํ ์ข ๋ฅ์ ๋ฌ๋ ฅ์ ํ์ฅ์ด ๊ฐ๋ฅํด์ผ ํ๋ค.
# 1-3. ์ฃผ์ API ํน์ง*
- ๊ธฐ๊ณ์ฉ ์๊ฐ(machine time)๊ณผ ์ธ๋ฅ์ฉ ์๊ฐ(human time)์ผ๋ก ๋๋ ์ ์๋ค.
- ๊ธฐ๊ณ์ฉ ์๊ฐ์
EPOCK
(1970๋ 1์ 1์ผ 0์ 0๋ถ 0์ด)๋ถํฐ ํ์ฌ๊น์ง์ ํ์์คํฌํ๋ฅผ ํ์ํ๋ค. - ์ธ๋ฅ์ฉ ์๊ฐ์ ์ฐ๋ฆฌ๊ฐ ํํ ์ฌ์ฉํ๋ ๋ , ์, ์ผ, ์, ๋ถ, ์ด ๋ฑ์ ๋งํ๋ค.
- ํ์์คํฌํ๋ Instant๋ฅผ ์ฌ์ฉํ๋ค.
- ํน์ ๋ ์ง(
LocalDate
), ์๊ฐ(LocalTime
), ์ผ์(LocalDateTime
)๋ฅผ ์ฌ์ฉํ ์ ์๋ค. - ๊ธฐ๊ฐ์ ํํํ ๋๋ Duration(์๊ฐ ๊ธฐ๋ฐ)๊ณผ Period(๋ ์ง ๊ธฐ๋ฐ)๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
DateTimeFormatter
๋ฅผ ์ฌ์ฉํด ์ผ์๋ฅผ ํน์ ํ ๋ฌธ์์ด๋ก ํฌ๋งคํ ํ ์ ์๋ค.
# 2. Date์ Time API
๊ธฐ๊ณ์ ์ธ ์๊ฐ๊ณผ ์ธ๋ฅ์ฉ ์๊ฐ์ ์ฌ์ฉ&ํํํ๋ ๋ฐฉ๋ฒ
# 2-1. ๊ธฐ๊ณ์ ์ธ ์๊ฐ
Instant.now()
: ํ์ฌ UTC(GMT)๋ฅผ ๋ฐํUniversal Time Coordinated == Greenwich Mean Time
public static void main(String[] args) throws InterruptedException {
Instant instant = Instant.now();//๊ธฐ์ค์ UTC (GMT)
System.out.println("instant = " + instant);
ZoneId zone = ZoneId.systemDefault();
System.out.println("zone = " + zone);
ZonedDateTime zonedDateTime = instant.atZone(zone);
System.out.println("zonedDateTime = " + zonedDateTime);
}
/*
instant = 2021-10-28T11:59:22.897293900Z
zone = Asia/Seoul
zonedDateTime = 2021-10-28T20:59:22.897293900+09:00[Asia/Seoul]
*/
ZoneId.systemDefault();
- ํ์ฌ ์์คํ ์์ zone ์ ๋ณด๋ฅผ ๋ฐํํฉ๋๋ค. (ex: Asia/Seoul)
instant.atZone(zone);
- UTC ๊ธฐ์ค์ด์๋ zone ์ ์์น ๊ธฐ๋ฐ์ ์๊ฐ์ ๋ฐํํฉ๋๋ค.
# 2-2. ์ธ๋ฅ์ฉ ์๊ฐ
LocalDate
์LocalDateTime
์ด ์๋ค.LocalDate
: ๋ /์/์ผ ๊น์ง ํํํ ๋ ์ฌ์ฉLocalDateTime
: ๋ /์/์ผ/์/๋ถ/์ด ๊น์ง ํํํ ๋ ์ฌ์ฉ
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now);
LocalDateTime birthDay = LocalDateTime.of(1988, Month.JUNE, 10, 0, 0, 0);
ZonedDateTime nowInUTC = ZonedDateTime.now(ZoneId.of("UTC"));
System.out.println("nowInUTC = " + nowInUTC);
ZonedDateTime birthDayByUTC = ZonedDateTime.of(1988, Month.JUNE.getValue(),10,0,0,0,0, ZoneId.of("UTC"));
System.out.println("birthDayByUTC = " + birthDayByUTC);
}
LocalDateTime.now()
- ํ์ฌ ์์คํ Zone์ ํด๋นํ๋(๋ก์ปฌ) ์ผ์๋ฅผ ๋ฐํ
LocalDateTime.of(1988, Month.JUNE, 10, 0, 0, 0);
- ๋ก์ปฌ์ ํน์ ์ผ์๋ฅผ ๋ฐํ
ZonedDateTime.now(ZoneId.of("UTC"));
- ํน์ Zone์ ํ์ฌ ์๊ฐ์ ๋ฐํํฉ๋๋ค.
ZonedDateTime.of(1988, Month.JUNE.getValue(),10,0,0,0,0, ZoneId.of("UTC"));
- ํน์ Zone์ ํน์ ์ผ์๋ฅผ ๋ฐํํฉ๋๋ค.
# 2-3. ๊ธฐ๊ฐ์ ํํํ๋ ๋ฐฉ๋ฒ
Period
- ๋ ์ง ๊ธฐ๊ฐ ๋จ์๋ฅผ ํํํ ๋ ์ฌ์ฉ
Duration
- ์๊ฐ ๋จ์ ๊ธฐ๊ฐ์ ํํํ ๋ ์ฌ์ฉ
public static void main(String[] args) {
LocalDate today = LocalDate.now();
LocalDate birthDay = LocalDate.of(2020, Month.JUNE, 10);
Period period = Period.between(birthDay, today);
System.out.println(period.getMonths()+"๊ฐ์ "+period.getDays()+"์ผ");
Period until = today.until(birthDay);
System.out.println("until.get(ChronoUnit.DAYS) = " + until.get(ChronoUnit.DAYS));
Instant now = Instant.now();
Instant plus = now.plus(10, ChronoUnit.SECONDS);
Duration duration = Duration.between(now, plus);
System.out.println(duration.getSeconds());
}
Period.between(birthDay, today)
- ์ฌํด ์์ผ๋ ์ง์ ์ค๋๊ณผ ๋น๊ตํ์ฌ Periodํ์ ์ ์ธ์คํด์ค๋ก ๋ฐํ
Period until = today.until(birthDay)
LocalDate
๊ฐ์ฒด์ until ๋ฉ์๋๋ฅผ ํตํด ์ ๋ฌํ ์ธ์๊ฐ๊ณผ ์ธ์คํด์ค์ ๊ธฐ๊ฐ์ ๊ณ์ฐํ Period ํ์ ์ ์ธ์คํด์ค๋ฅผ ๋ฐํ
Duration.between(now, plus)
- ํ์ฌ์๊ฐ๊ณผ 10์ด ๋ค์ ์๊ฐ์ ์ธ์คํด์ค๋ก ๋ง๋ ๋ค ๋น๊ตํ์ฌ Duration ํ์ ์ ์ธ์คํด์ค๋ก ๋ฐํ
# 2-4. ํ์ฑ ๋๋ ํฌ๋งคํ
LocalDateTime
์ ๊ฐ์ง๊ณ ๋ฌธ์์ด์LocalDateTime
์ผ๋ก ํน์ ๋ฐ๋๋ก ๋ณํํด์ฃผ๋ ๋ฐฉ๋ฒ.LocalDateTime.parse(String, DateTimeFormatter);
- ๊ธฐ๋ณธ ์ ์ ํฌ๋งทํ ์์์ ๋ณด์ ํจํด์ ๋ณด ์ฐธ์กฐ (opens new window)
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter MMddyyyy = DateTimeFormatter.ofPattern("MM/dd/yyyy");
System.out.println(now.format(DateTimeFormatter.BASIC_ISO_DATE));
System.out.println(now.format(MMddyyyy));
LocalDate birthDay = LocalDate.parse("06/10/1988", MMddyyyy);
System.out.println(birthDay);
}
DateTimeFormatter.ofPattern("MM/dd/yyyy")
DateTimeFormatter
๋ฅผ ์ด์ฉํด ๊ฐ์ข ํ์์ผ๋กLocalDateTime
์ ํฌ๋งทํ ํด์ค ์ ์์ต๋๋ค.ofPattern("MM/dd/yyy")
๋ ์ฌ์ฉ์ ์ ์ ํจํด์ผ๋ก ํฌ๋งทํ ์ ํ๊ฒ ๋ค๋ ์๋ฏธ์ ๋๋ค.
now.format(DateTimeFormatter.BASIC_ISO_DATE)
- ์๊ฐ์
DateTimeFormatter
๊ฐ ์ง์ํ๋BASIC_ISO_DATE
ํํ๋ก ํฌ๋งทํ
- ์๊ฐ์
now.format(MMddyyyy)
- ์์์
ofPattern
์ผ๋ก ์ง์ ํ ํจํด์ผ๋ก ์๊ฐ์ ํฌ๋งคํ
- ์์์
LocalDate.parse("06/10/1988", MMddyyyy)
- ๋ฌธ์์ด์
ofPattern
์์ ์ ์ธํ ํจํด ๋ฐฉ์์ผ๋ก ํ์ฑํ์ฌLocalDate
ํ์ ์ ์ธ์คํด์ค๋ฅผ ์์ฑํด ๋ฐํ
- ๋ฌธ์์ด์
# 2-5. ๋ ๊ฑฐ์ API ์ง์
์์ ์ ๊ตฌํ ๋ฐ ์ฌ์ฉํ๋ ๋ ์ง์ ์๊ฐ(Date) API์ ํ์ฌ ์ถ๊ฐ๋ LocalDate, LocalDateTime, Instant๋ ์๋ก ํธํ ๋๋ค!
public static void main(String[] args) {
Date date = new Date();
Instant instant = date.toInstant();
Date newDate = Date.from(instant);
GregorianCalendar gregorianCalendar = new GregorianCalendar();
LocalDateTime dateTime = gregorianCalendar.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
ZonedDateTime zonedDateTime = ZonedDateTime.from(dateTime);
GregorianCalendar from = GregorianCalendar.from(zonedDateTime);
ZoneId zoneId = TimeZone.getTimeZone("PST").toZoneId();
TimeZone timeZone = TimeZone.getTimeZone(zoneId);
}
- GregorianCalendar์ Date ํ์ ์ ์ธ์คํด์ค๋ฅผ Instant๋ ZonedDateTime์ผ๋ก ๋ณํ
- java.util.TimeZone์์ java.time.ZoneId๋ก ์ํธ ๋ณํ ๊ฐ๋ฅ
# Reference
โ Optional CompletableFuture โ