Post

🦊 chap12. μƒˆλ‘œμš΄ λ‚ μ§œμ™€ μ‹œκ°„ API

chap12. μƒˆλ‘œμš΄ λ‚ μ§œμ™€ μ‹œκ°„ API

12.1 LocalDate, LocalTime, Instant, Duration, Period 클래슀

12.1.1 LocalDate와 LocalTime μ‚¬μš©

LocalDate μΈμŠ€ν„΄μŠ€λŠ” μ‹œκ°„μ„ μ œμ™Έν•œ λ‚ μ§œλ₯Ό ν‘œν˜„ν•˜λŠ” λΆˆλ³€ 객체닀.

1
2
3
4
5
6
7
LocalDate date = LocalDate.of(2017, 9, 21);
int year = date.getYear();
Month month = date.getMonth();
int day = date.getDayOfMonth();
DayOfWeek dow = date.getDayOfWeek();
int len = date.lengthOfMonth();
boolean leap = date.isLeapYear();

νŒ©ν† λ¦¬ λ©”μ„œλ“œ now λŠ” μ‹œμŠ€ν…œ μ‹œκ³„μ˜ 정보λ₯Ό μ΄μš©ν•΄μ„œ ν˜„μž¬ λ‚ μ§œ 정보λ₯Ό μ–»λŠ”λ‹€.

1
LocalDate today = LocalDate.now();

get λ©”μ„œλ“œμ— TemporalField μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ „λ‹¬ν•΄μ„œ 정보λ₯Ό μ–»λŠ” 방법도 μžˆλ‹€.

μ—΄κ±°μž ChronoField λŠ” TemporalField μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•œλ‹€.

1
2
3
int year = date.get(ChronoField.YEAR);
int month = date.get(ChronoField.MONTH_OF_YEAR);
int day = date.get(ChronoField.DAY_OF_MONTH);

λ‚΄μž₯ λ©”μ„œλ“œλ₯Ό μ΄μš©ν•΄ 가독성을 높일 μˆ˜λ„ μžˆλ‹€.

1
2
3
int year = date.getYear();
int month = date.getMonthValue();
int day = date.getDayOfMonth();

μ‹œκ°„μ„ LocalTime 클래슀둜 ν‘œν˜„ν•  μˆ˜λ„ μžˆλ‹€.

1
2
3
4
LocalTime time = LocalTime.of(13, 45, 20);
int hour = time.getHour();
int minute = time.getMinute();
int second = time.getSecond();

λ‚ μ§œμ™€ μ‹œκ°„ λ¬Έμžμ—΄λ‘œ parse 정적 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•΄ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€ μˆ˜λ„ μžˆλ‹€.

1
2
LocalDate date = LocalDate.parse("2017-09-21");
LocalTime time = LocalTime.parse("13:45:20");

parse λ©”μ„œλ“œμ—λŠ” DateTimeFormatter λ₯Ό 전달할 μˆ˜λ„ μžˆλ‹€.

12.1.2 λ‚ μ§œμ™€ μ‹œκ°„ μ‘°ν•©

LocalDateTime 은 LocalDate 와 LocalTime 을 쌍으둜 κ°–λŠ” 볡합 ν΄λž˜μŠ€μ΄λ‹€.

1
2
3
4
5
LocalDateTime dt1 = LocalDateTime.of(2017, Month.SEPTEMBER, 21, 13, 45, 20);
LocalDateTime dt2 = LocalDateTime.of(date, time);
LocalDateTime dt3 = date.atTime(13, 45, 20);
LocalDateTime dt4 = date.atTime(time);
LocalDateTime dt5 = time.atDate(date);

LocalDateTime μ—μ„œ 각 μΈμŠ€ν„΄μŠ€λ₯Ό μΆ”μΆœν•  μˆ˜λ„ μžˆλ‹€.

1
2
LocalDate date1 = dt1.toLocalDate();
LocalTime time1 = dt1.toLocalTime();

12.1.3 Instant 클래슀 : κΈ°κ³„μ˜ λ‚ μ§œμ™€ μ‹œκ°„

κΈ°κ³„μ˜ κ΄€μ μ—μ„œλŠ” μ—°μ†λœ μ‹œκ°„μ—μ„œ νŠΉμ • 지점을 ν•˜λ‚˜μ˜ 큰 수둜 ν‘œν˜„ν•˜λŠ” 것이 κ°€μž₯ μžμ—°μŠ€λŸ¬μš΄ μ‹œκ°„ ν‘œν˜„ 방식이닀.

java.time.Instant ν΄λž˜μŠ€μ—μ„œλŠ” 기계적인 κ΄€μ μ—μ„œ μ‹œκ°„μ„ ν‘œν˜„ν•œλ‹€.

μ΄λŠ” μœ λ‹‰μŠ€ 에포크 μ‹œκ°„ Unix epoch time, 1970-01-01 00:00:00 UTC을 κΈ°μ€€μœΌλ‘œ νŠΉμ • μ‹œμ κΉŒμ§€μ˜ μ‹œκ°„μ„ 초둜 ν‘œν˜„ν•œλ‹€.

1
2
3
4
Instant.ofEpochSecond(3);
Instant.ofEpochSecond(3, 0);
Instant.ofEpochSecond(2, 1_000_000_000);
Instant.ofEpochSecond(4, -1_000_000_000);

Instant ν΄λž˜μŠ€λ„ μ‚¬λžŒμ΄ 확인할 수 μžˆλ„λ‘ μ‹œκ°„μ„ ν‘œμ‹œν•΄μ£ΌλŠ” 정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œ now λ₯Ό μ œκ³΅ν•œλ‹€.

Instant λŠ” μ΄ˆμ™€ λ‚˜λ…Έμ΄ˆ 정보λ₯Ό ν¬ν•¨ν•œλ‹€.

이λ₯Ό 읽기 μœ„ν•΄ Duration κ³Ό Period 클래슀λ₯Ό ν™œμš©ν•  수 μžˆλ‹€.

12.1.4 Duration κ³Ό Period μ •μ˜

μ§€κΈˆκΉŒμ§€μ˜ λͺ¨λ“  ν΄λž˜μŠ€λŠ” Temporal μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œλ‹€.

Duration 클래슀의 정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œ between 으둜 두 μ‹œκ°„ 객체 μ‚¬μ΄μ˜ μ§€μ†μ‹œκ°„μ„ λ§Œλ“€ 수 μžˆλ‹€.

1
2
3
Duration d1 = Duration.between(time1, time2);
Duration d2 = Duration.between(dateTime1, dateTime2);
Duration d3 = Duration.between(instant1, instant2);

λ‹€λ§Œ LocalDateTime 은 μ‚¬λžŒμ΄ μ‚¬μš©ν•˜λ„λ‘, Instant λŠ” 기계가 μ‚¬μš©ν•˜λ„λ‘ λ§Œλ“€μ–΄μ§„ 클래슀둜

두 μΈμŠ€ν„΄μŠ€λŠ” μ„œλ‘œ ν˜Όν•©ν•  수 μ—†λ‹€.

λ…„, μ›” 일둜 μ‹œκ°„μ„ ν‘œν˜„ν•  λ•ŒλŠ” Period 클래슀λ₯Ό μ‚¬μš©ν•œλ‹€.

1
2
Period tenDays = Period.between(LocalDate.of(2017, 9, 11),
															LocalDate.of(2017, 9, 21));

Duration κ³Ό Period ν΄λž˜μŠ€λŠ” μžμ‹ μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€ 수 μžˆλ„λ‘ λ‹€μ–‘ν•œ νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•œλ‹€.

1
2
3
4
5
6
Duration threeMinutes = Duration.ofMinutes(3);
Duration threeMinutes = Duration.of(3, ChronoUnit.MINUTES);

Period tenDays = Period.ofDays(10);
Period threeWeeks = Period.ofWeeks(3);
Period twoYearsSixMonthsOnday = Period.of(2, 6, 1);

μ§€κΈˆκΉŒμ§€μ˜ λͺ¨λ“  ν΄λž˜μŠ€λŠ” λΆˆλ³€ ν΄λž˜μŠ€μ΄λ‹€.

12.2 λ‚ μ§œ μ‘°μ •, νŒŒμ‹±, ν¬λ§€νŒ…

withArrtibute λ©”μ„œλ“œλ‘œ 기쑴의 LocalDate λ₯Ό λ°”κΎΌ 버전을 직접 κ°„λ‹¨ν•˜κ²Œ λ§Œλ“€ 수 μžˆλ‹€.

1
2
3
4
LocalDate date1 = LocalDate.of(2017, 9, 21);
LocalDate date2 = date1.withYear(2011);
LocalDate date3 = date2.withDayOfMonth(25);
LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 2);

Temproal μΈν„°νŽ˜μ΄μŠ€λŠ” LocalDate, LocalTime, LocalDateTime, Instant 처럼 νŠΉμ • μ‹œκ°„μ„ μ •μ˜ν•˜κ³ 

get κ³Ό with λ©”μ„œλ“œλ‘œ Temporal 객체의 ν•„λ“œκ°’μ„ μ½κ±°λ‚˜ κ³ μΉ  수 μžˆλ‹€.

λ§Œμ•½ μ§€μ •λœ ν•„λ“œλ₯Ό μ§€μ›ν•˜μ§€ μ•ŠμœΌλ©΄ UnsupportedTemporalTypeException 이 λ°œμƒν•œλ‹€.

μ„ μ–Έν˜•μœΌλ‘œ LocalDate λ₯Ό μ‚¬μš©ν•˜λŠ” 방법도 μžˆλ‹€.

1
2
3
4
LocalDate date1 = LcoalDate.of(2017, 9, 21);
LocalDate date2 = date1.plusWeeks(1);
LocalDate date3 = date2.minusYears(6);
LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS);

plus, minus λ©”μ„œλ“œλ„ Temporal μΈν„°νŽ˜μ΄μŠ€μ— μ •μ˜λ˜μ–΄ μžˆλ‹€.

이λ₯Ό ν™œμš©ν•΄ νŠΉμ • μ‹œκ°„λ§ŒνΌ μ•žλ’€λ‘œ μ΄λ™μ‹œν‚¬ 수 μžˆλ‹€.

μˆ«μžμ™€ TemporalUnit 을 인수둜 ν™œμš©ν•  수 μžˆλ‹€.

12.2.1 TemporalAdjusters μ‚¬μš©ν•˜κΈ°

TemporalAdjuster λŠ” with λ©”μ„œλ“œμ— μ’€ 더 λ‹€μ–‘ν•œ λ™μž‘μ„ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ ν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€.

1
2
3
4
5
import static java.time.tempoal.TemporalAdjusters.*;

LocalDate date1 = LocalDate.of(2014, 3, 18);
LocalDate date2 = date1.with(nextOfSame(DayOfWeek.SUNDAY));
LocalDate date3 = date2.with(lastDayOfMonth());

ν•„μš”ν•œ κΈ°λŠ₯이 μ •μ˜λ˜μ–΄ μžˆμ§€ μ•Šμ„ λ•ŒλŠ” 비ꡐ적 μ‰½κ²Œ μ»€μŠ€ν…€ TemporalAdjuster κ΅¬ν˜„μ„ λ§Œλ“€ 수 μžˆλ‹€.

1
2
3
4
@FunctionalInterface
public interface TemporalAdjuster {
	Temporal adjustInto(Temporal temporal);
}

TemporalAdjuster μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„μ€ Temporal 객체λ₯Ό μ–΄λ–»κ²Œ λ‹€λ₯Έ Temporal 객체둜 λ³€ν™˜ν•  지 μ •μ˜ν•œλ‹€.

12.2.2 λ‚ μ§œμ™€ μ‹œκ°„ 객체 좜λ ₯κ³Ό νŒŒμ‹±

ν¬λ§€νŒ…κ³Ό νŒŒμ‹± μ „μš© νŒ¨ν‚€μ§€μΈ java.time.format 이 μΆ”κ°€λ˜μ—ˆλ‹€.

κ°€μž₯ μ€‘μš”ν•œ ν΄λž˜μŠ€λŠ” DateTimeFormatter 이닀.

이λ₯Ό μ΄μš©ν•΄μ„œ λ‚ μ§œλ‚˜ μ‹œκ°„μ„ νŠΉμ • ν˜•μ‹μ˜ λ¬Έμžμ—΄λ‘œ λ§Œλ“€ 수 μžˆλ‹€.

1
2
3
LocalDate date = LocalDate.of(2014, 3, 18);
String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); // 20140318
String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2014-03-18

λ°˜λŒ€λ‘œ λ¬Έμžμ—΄μ„ νŒŒμ‹±ν•΄μ„œ λ‚ μ§œ 객체λ₯Ό λ‹€μ‹œ λ§Œλ“€ 수 μžˆλ‹€.

1
2
LocalDate date1 = LocalDate.parse("20140318", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date2 = LocalDate.parse("2014-03-18", DateTimeFormatter.ISO_LOCAL_DATE);

κΈ°μ‘΄ java.util.DateFormat κ³Ό 달리 λͺ¨λ“  DateTimeFormatter λŠ” μŠ€λ ˆλ“œ μ•ˆμ „ν•œ ν΄λž˜μŠ€μ΄λ‹€.

λ˜ν•œ νŠΉμ • νŒ¨ν„΄μœΌλ‘œ 포맀터λ₯Ό λ§Œλ“€ 수 μžˆλŠ” 정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œλ„ μ œκ³΅ν•œλ‹€.

1
2
3
4
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date1 = LocalDate.of(2014, 3, 18);
String formattedDate = date1.format(formatter);
LocalDate date2 = LocalDate.parse(formattedDate, formatter);

ofPattern λ©”μ„œλ“œλ„ Locale 둜 포맀터λ₯Ό λ§Œλ“€ 수 μžˆλ„λ‘ μ˜€λ²„λ‘œλ“œλœ λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•œλ‹€.

1
2
3
DateTimeFormatter italianFormatter =
			DateTimeFormatter.ofPattern("d. MMMM yyyy", Locale.ITALIAN);
...

DateTimeFormatterBuilder 클래슀둜 볡합적인 포맀터λ₯Ό μ •μ˜ν•΄μ„œ μ„ΈλΆ€μ μœΌλ‘œ μ œμ–΄ν•  μˆ˜λ„ μžˆλ‹€.

1
2
3
4
5
6
7
8
DateTimeFormatter italianFormatter = new DateTimeFormatterBuilder()
			.appendText(ChronoField.DAY_OF_MONTH)
			.appendLiteral(". ")
			.appendText(ChronoField.MONTH_OF_YEAR)
			.appendLiteral(" ")
			.appendText(ChronoField.YEAR)
			.parseCaseInsensitive()
			.toFormatter(Locale.ITALIAN);

12.3 λ‹€μ–‘ν•œ μ‹œκ°„λŒ€μ™€ μΊ˜λ¦°ν„° ν™œμš© 방법

기쑴의 java.util.TimeZone 을 λŒ€μ²΄ν•  수 μžˆλŠ” java.time.ZoneId ν΄λž˜μŠ€κ°€ μƒˆλ‘­κ²Œ λ“±μž₯ν–ˆλ‹€.

이 클래슀λ₯Ό μ΄μš©ν•˜λ©΄ μ¨λ¨Ένƒ€μž„(DST) 같은 λ³΅μž‘ν•œ 사항이 μžλ™μœΌλ‘œ μ²˜λ¦¬λœλ‹€.

ZoneId ν΄λž˜μŠ€λŠ” λΆˆλ³€μ΄λ‹€.

12.3.1 μ‹œκ°„λŒ€ μ‚¬μš©ν•˜κΈ°

ZoneRules ν΄λž˜μŠ€μ—λŠ” μ•½ 40개 μ •λ„μ˜ μ‹œκ°„λŒ€κ°€ 있고, getRules() λ₯Ό μ΄μš©ν•΄ ν•΄λ‹Ή μ‹œκ°„λŒ€μ˜ κ·œμ •μ„ νšλ“ν•  수 μžˆλ‹€.

1
ZoneId romeZone = ZoneId.of("Europe/Rome");

지역 ID λŠ” 지역/λ„μ‹œ ν˜•μ‹μœΌλ‘œ 이루어지고 IANA Time Zone Datebase μ—μ„œ μ œκ³΅ν•˜λŠ” 지역 집합 정보λ₯Ό μ‚¬μš©ν•œλ‹€.

ZoneId 객체λ₯Ό 얻은 λ‹€μŒμ—λŠ” LocalDate, LocalDateTime, Instant λ₯Ό μ΄μš©ν•΄μ„œ ZoneDateTime μΈμŠ€ν„΄μŠ€λ‘œ λ³€ν™˜ν•  수 μžˆλ‹€.

1
2
3
4
5
6
LocalDate date = LocalDate.of(2014, Month.MARCH, 18);
ZonedDateTime zdt1 = date.atStartOfDay(romeZone);
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
ZonedDateTime zdt2 = dateTime.atZone(romeZone);
Instant instant = Instant.now();
ZonedDateTime zdt3 = instant.atZone(romeZone);

ZoneId λ₯Ό μ΄μš©ν•΄μ„œ LocalDateTime 을 Instant 둜 λ°”κΏ€ 수 μžˆλ‹€.

1
2
Instant instant = Instant.now();
LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant, romeZone);

12.3.2 UTC/Greenwich κΈ°μ€€μ˜ κ³ μ • μ˜€ν”„μ…‹

λ•Œλ‘œλŠ” ν˜‘μ • μ„Έκ³„μ‹œ(UTC)/κ·Έλ¦¬λ‹ˆμΉ˜ ν‘œμ€€μ‹œ(GMT) λ₯Ό κΈ°μ€€μœΌλ‘œ ν‘œν˜„ν•˜κΈ°λ„ ν•œλ‹€.

ZoneId 의 μ„œλΈŒν΄λž˜μŠ€μΈ ZoneOffset 클래슀둜 런던의 κ·Έλ¦¬λ‹ˆμΉ˜ 0도 μžμ˜€μ„ κ³Ό μ‹œκ°„κ°’μ˜ 차이λ₯Ό ν‘œν˜„ν•  수 μžˆλ‹€.

1
ZoneOffset newYorkOffset = ZoneOffset.of("-05:00");

μ΄λŠ” μ„œλ¨Ένƒ€μž„μ„ μ œλŒ€λ‘œ μ²˜λ¦¬ν•  수 μ—†μ–΄ ꢌμž₯ν•˜μ§€ μ•ŠλŠ”λ‹€.

ISO-8601 μΊ˜λ¦°λ” μ‹œμŠ€ν…œμ—μ„œ μ •μ˜ν•˜λŠ” UTC/GMT 와 μ˜€ν”„μ…‹μœΌλ‘œ λ‚ μ§œμ™€ μ‹œκ°„μ„ ν‘œν˜„ν•˜λŠ” OffsetDateTime 을 λ§Œλ“œλŠ” 방법도 μžˆλ‹€.

1
2
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
OffsetDateTime dateTimeInNewYork = OffsetDateTime.of(date, newYorkOffset);

12.3.3 λŒ€μ•ˆ μΊ˜λ¦°λ” μ‹œμŠ€ν…œ μ‚¬μš©ν•˜κΈ°

μžλ°” 8μ—μ„œλŠ” μΆ”κ°€λ‘œ 4개의 μΊ˜λ¦°λ” μ‹œμŠ€ν…œμ„ μ œκ³΅ν•œλ‹€.

ThaiBuddhistDate, MinguoDate, JapaneseDate, HijrahDate 이닀.

이 ν΄λž˜μŠ€μ™€ LocalDate ν΄λž˜μŠ€λŠ” ChronoLocalDAte μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ”λ° μ΄λŠ” μž„μ˜μ˜ μ—°λŒ€κΈ°μ—μ„œ νŠΉμ • λ‚ μ§œλ₯Ό ν‘œν˜„ν•  수 μžˆλŠ” κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€μ΄λ‹€.

1
2
LocalDate date = LocalDate.of(2014, Month.MARCH, 18);
JapaneseDate japaneseDate = JapaneseDate.from(date);

νŠΉμ • Locale κ³Ό Locale 에 λŒ€ν•œ λ‚ μ§œ μΈμŠ€ν„΄μŠ€λ‘œ μΊ˜λ¦°λ” μ‹œμŠ€ν…œμ„ λ§Œλ“€μˆ˜λ„ μžˆλ‹€.

1
2
Chronology japaneseChronology = Chronology.ofLocale(Locale.JAPAN);
ChronoLocalDate now = japaneseChronology.dateNow();

λ‚ μ§œμ™€ μ‹œκ°„ API 의 μ„€κ³„μžλŠ” ChronoLocalDate λ³΄λ‹€λŠ” LocalDate λ₯Ό μ‚¬μš©ν•˜λΌκ³  κΆŒκ³ ν•œλ‹€.

This post is licensed under CC BY 4.0 by the author.