본문 바로가기
Study/JAVA

[Java] 10-3. java.time 패키지

by jeongwle 2022. 9. 19.
728x90
반응형

 

java.time패키지

Date와 Calendar가 가지고 있던 단점을 해소하기 위해 JDK1.8부터 java.time패키지가 추가되었다.

패키지 설명
 java.time  날짜와 시간을 다루는데 필요한 핵심 클래스들을 제공
 java.time.chrono  표준(ISO)이 아닌 달력 시스템을 위한 클래스들을 제공
 java.time.format  날짜와 시간을 파싱하고, 형식화하기 위한 클래스들을 제공
 java.time.temporal  날짜와 시간의 필드(field)와 단위(unit)를 위한 클래스들을 제공
 java.time.zone  시간대(time-zone)와 관련된 클래스들을 제공

위의 표는 java.time 패키지와 서브 패키지들이다. 위의 패키지들에 속한 클래스의 큰 특징은 String클래스처럼 불변이라는 것이다. 날짜나 시간을 변경하는 메서드들은 기존의 객체를 변경하는 대신 항상 새로운 객체를 반환한다. Calendar클래스는 변경이 가능하여 멀티 쓰레드 환경에서 안전하지 못하다.

 

1. java.time패키지의 핵심 클래스

java.time패키지는 날짜와 시간을 별도의 클래스로 분리해 놓았다. 시간을 표현할 때는 LocalTime클래스를 사용하고 날짜를 표현할 때는 LocalDate클래스를 사용한다. 날짜와 시간이 모두 필요할 때는 LocalDateTime클래스를 사용하면 된다. 만약 시간대(time-zone)까지 다루어야 한다면 ZonedDateTime 클래스를 사용하자.

LocalDate(날짜)  +  LocalTime(시간)  -> LocalDateTime(날짜 & 시간)

LocalDateTime  + 시간대  -> ZonedDateTime​


Period와 Duration
날짜와 시간의 간격을 표현하기 위한 클래스이다. Period는 두 날짜간의 차이를 표현하기 위한 것이고, Duration은 시간의 차이를 표현하기 위한 것이다.

날짜  -  날짜  =  Period
시간  -  시간  =  Duration​


객체 생성하기 - now(), of()
java.time 패키지에 속한 클래스의 객체를 생성하는 가장 기본적인 방법은 now()와 of()를 사용하는 것이다. now()는 현재 날짜와 시간을 저장하는 객체를 생성한다. of()는 단순히 해당 필드의 값을 순서대로 지정해주기만 하면 된다. 각 클래스마다 다양한 of()가 정의되어 있다.

LocalDate date = LocalDate.now();		// 2022-09-19
LocaTime time = LocalTime.now();		// 13:13:20.875

LocalDate date = LocalDate.of(2022, 9, 19);	// 2022년 9월 19일
LocalTime time = LocaTime.now(13, 13, 13);	// 13시 13분 13초​


Temporal과 TemporalAmount
LocalDate, LocalTime, LocalDateTime, ZonedDateTime등 날짜와 시간을 표현하기 위한 클래스들은 모두 Temporal, TemporalAccessor, TemporalAdjuster 인터페이스를 구현했고, Duration, Period는 TemporalAmount인터페이스를 구현하였다. 앞으로 소개할 메서드 중 매개변수 타입이 Temporal로 시작하는 것들이 많을텐데 대부분 날짜와 시간을 위한 것이므로 TemporalAmount인지 아닌지만 확인하면 된다.

Temporal, TemporalAccessor, TemporalAdjuster를 구현한 클래스
  - LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant 등
  
TemporalAmount를 구현한 클래스
  - Period, Duration​


TemporalUnit과 TemporalField
날짜와 시간의 단위를 정의해 놓은 것이 TemporalUnit인터페이스이고, 이 인터페이스를 구현한 것이 열거형 ChoronoUnit이다. TemporalField는 년, 월, 일 등 날짜와 시간의 필드를 정의해 놓은 것으로 열거형 ChoronoField가 이 인터페이스를 구현하였다.

날짜와 시간에서 특정 필드의 값만을 얻을 때는 get()이나, get으로 시작하는 이름의 메서드를 이용한다. 그리고 특정 날짜와 시간에서 지정된 단위의 값을 더하거나 뺄 때는 plus() 또는 minus()에 값과 함께 열거형 ChronoUnit을 사용한다.

LocalTime now = LocalTime.now();
int minute = now.getMinute();	// 현재 시간에서 분만 뽑아낸다.
int minute = now.get(ChronoField.MINUTE_OF_HOUR); // 위와 동일

LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS);
LocalDate tomorrow = today.plusDays(1); // 위와 동일​


특정 TemporalField나 TemporalUnit을 사용할 수 있는지 확인하는 메서드는 다음과 같다. 이 메서드들은 날짜와 시간을 표현하는 데 사용하는 모든 클래스에 포함되어 있다.

boolean isSupported(TemporalUnit unit)    // Temporal에 정의
boolean isSupported(TemporalField field)  // TemporalAccessor에 정의​

 

2. LocalDate와 LocalTime

LocalDate와 LocalTime은 java.time패키지의 가장 기본이 되는 클래스이다. 나머지 클래스들은 이들의 확장이므로 이 두 클래스를 잘 이해하면 나머지는 쉬워진다고 한다. now()와 of()로 객체를 생성하는 데 둘 다 static메서드이다. of()는 여러 가지 버전이 제공된다.

static LocalDate of(int year, Month month, int dayOfMonth)
static LocalDate of(int year, int month, int dayOfMonth)

static LocalTime of(int hour, int min)
static LocalTime of(int hour, int min, int sec)
static LocalTime of(int hour, int min, int sec, int nanoOfSecond)​


특정 필드의 값 가져오기 - get(), getXXX()
클래스 메서드 설명(1999-12-31 23:59:59)
 LocalDate  int                getYear()  년도(1999)
 int                getMonthValue()  월(12)
 Month          getMonth()  월(DECEMBER) getMonth().getValue() = 12
 int                getDayOfMonth()  일(31)
 int                getDayOfYear()  같은 해의 1월 1일부터 몇번쨰 일(365)
 DayOfWeek getDayOfWeek()  요일(FRIDAY) getDayOfWeek().getValue() = 5
 int                lengthOfMonth()  같은 달의 총 일수(31)
 int                lengthOfYear()  같은 해의 총 일수 (365). 윤년이면 366
 boolean       isLeapYear()  윤년여부 확인(false)
 LocalTime  int                getHour()  시(23)
 int                getMinute()  분(59)
 int                getSecond()  초(59)
 int                getNano()  나노초(0)

위의 표에 소개된 메서드 외에도 get()과 getLong()이 있는데 원하는 필드를 직접 지정할 수 있다. 대부분의 필드는 int타입의 범위에 속하지만 몇몇은 범위를 넘을 수 있고 그 때 getLong()을 사용해야 한다. 밑의 표에서 *표시가 되어있는 것이 getLong()을 사용해야 하는 것들이다.

int	get    (TemporalField field)
long	getLong(TemporalField field)​


TemporalField(ChronoField) 설명
 ERA  시대
 YEAR_OF_ERA, YEAR  년
 MOTN_OF_YEAR  월
 DAY_OF_WEEK  요일(1 : 월요일, 2 : 화요일, ... 7 : 일요일)
 DAY_OF_MONTH  일
 AMPM_OF_DAY  오전 / 오후
 HOUR_OF_DAY  시간(0 ~ 23)
 CLOCK_HOUR_OF_DAY  시간(1 ~ 24)
 HOUR_OF_AMPM  시간(0 ~ 11)
 CLOCK_HOUR_OF_AMPM  시간(1 ~ 12)
 MINUTE_OF_HOUR  분
 SECOND_OF_MINUTE  초
 MILLI_OF_SECOND  천분의 일초(10⁻³)
 MICRO_OF_SECOND *  백만분의 일초(10⁻⁶)
 NANO_OF_SECOND *  10억분의 일초(10⁻⁹)
 DAY_OF_YEAR  그 해의 몇번째 날
 EPOCH_DAY *  EPOCH(1970.1.1)부터 몇 번째 날
 MINUTE_OF_DAY  그 날의 몇 번째 분(시간을 분으로 환산)
 SECOND_OF_DAY  그 날의 몇 번째 초(시간을 초로 환산)
 MILLI_OF_DAY  그 날의 몇 번째 밀리초(10⁻³)
 MICRO_OF_DAY *  그 날의 몇 번째 마이크로초(10⁻⁶)
 NANO_OF_DAY *  그 날의 몇 번째 나노초(10⁻⁹)
 ALIGNED_WEEK_OF_MONTH  그 달의 n번째 주(1 ~ 7일 1주, 8 ~ 14일 2주, ...)
 ALIGNED_WEEK_OF_YEAR  그 해의 n번째 주(1월 1 ~ 7일 1주, 8 ~ 14일 2주, ...)
 ALIGNED_DAY_OF_WEEK_IN_MONTH  요일(그 달의 1일을 월요일로 간주하여 계산)
 ALIGNED_DAY_OF_WEEK_IN_YEAR  요일(그 해의 1월 1일을 월요일로 간주하여 계산)
 INSTANT_SECONDS  년월일을 초단위로 환산. Instant에만 사용 가능
 (1970-01-01 00:00:00 UTC를 0초로 기준)
 OFFSET_SECONDS  UTC와의 시차. ZoneOffset에만 사용 가능
 PROLEPTIC_MONTH  년월을 월단위로 환산(2015년 11월 = 2015 * 12 + 11)

이 목록은 ChronoField에 정의된 모든 상수이다. 사용할 수 있는 필드는 클래스마다 다르다.

필드의 값 변경하기 - with(), plus(), minus()
날짜와 시간에서 특정 필드 값을 변경하려면 다음과 같이 with로 시작하는 메서드를 사용하면 된다.

LocalDate withYear(int year)
LocalDate withMonth(int month)
LocalDate withDayOfMonth(int dayOfMonth)
LocalDate withDayOfYear(int dayOfYear)

LocalTime withHour(int hour)
LocalTime withMinute(int minute)
LocalTime withSecond(int second)
LocalTime withNano(int nanoOfSecond)

LocalDate with(TemporalField field, long newValue)​


이 외에도 특정 필드에 값을 더하거나 빼는 plus()와 minus()가 있다.

LocalTime plus(TemporalAmount amountToAdd)
LocalTime plus(long amountToAdd, TemporalUnit unit)

LocalDate plus(TemporalAmount amountToAdd)
LocalDate plus(long amountToAdd, TemporalUnit unit)

LocalDate plusYears(long yearsToAdd)
LocalDate plusMonths(long monthsToAdd)
LocalDate plusDays(long daysToAdd)
LocalDate plusWeeks(long weeksToAdd)

LocalTime plusHours(long hoursToAdd)
LocalTime plusMinutes(long minutesToAdd)
LocalTime plusSeconds(long secondsToAdd)
LocalTime plusNanos(long nanosToAdd)​

LocalTime의 truncatedTo()는 지정된 것보다 작은 단위의 필드를 0으로 만든다.

LocalTime time = LocalTime.of(12, 34, 56); // 12시 34분 56초
time = time.truncatedTo(ChronoUnit.HOURS); // 시(hour)보다 작은 단위를 0으로
System.out.println(time);	// 12:00​

LocalTime과 달리 LocalDate에는 truncatedTo()가 없는데 년, 월, 일은 0이 될 수 없기 때문이다. 그리고 이 메서드의 매개변수로는 아래의 표 중에서 시간과 관련된 필드만 사용가능하다.

TemporalUnit(ChronoUnit) 설명
 FOREVER  Long.MAX_VALUE초(약 3천억년)
 ERAS  1,000,000,000년(10억)
 MILLENNIA  1,000년
 CENTURIES  100년
 DECADES  10년
 YEARS  년
 MONTHS  월
 WEEKS  주
 DAYS  일
 HALF_DAYS  반나절
 HOURS  시
 MINUTES  분
 SECONDS  초
 MILLIS  천분의 일초(10⁻³)
 MICROS  마이크로초(10⁻⁶)
 NANOS  나노초(10⁻⁹)


날짜와 시간의 비교 - isAfter(), isBefore(), isEqual()
LocalDate와 LocalTime도 compareTo()가 적절히 오버라이딩되어 있어서 compareTo()로 비교할 수 있다. 하지만 보다 편리한 메서드들이 추가로 제공된다.

boolean isAfter(ChronoLocalDate other)
boolean isBefore(ChronoLocalDate ohter)
boolean isEqual(ChronoLocalDate ohter)	// LocalDate에만 있음​

equals()가 있는데도 isEqual()을 제공하는 이유는 연표(chronology)가 다른 두 날짜를 비교하기 위해서이다. 모든 필드가 일치해야하는 equals()와 달리 isEqual()은 오직 날짜만 비교한다.

 

3. Instant

Instant는 에포크 타임(EPOCH TIME, 1970-01-01 00:00:00 UTC)부터 경과된 시간을 나노초 단위로 표현한다. 사람에겐 불편하지만 단일 진법으로만 다루기 때문에 계산하기 쉽다.

Instant now = Instant.now();
Instant now2 = Instant.ofEpochSecond(now.getEpochSecond());
Instant now3 = Instant.ofEpochSecond(now.getEpochSecond(), now.getNano());​

Instant를 생성할 때는 위와 같이 now()와 ofEpochSecond()를 사용한다. Instant는 시간을 초 단위와 나노초 단위로 나누어 저장한다. 밀리초  단위의 EPOCH TIME이 필요할 경우엔 toEpochMilli()를 사용하면 된다.

long toEpochMilli()​

Instant는 항상 UTC(+00:00)를 기준으로 하기 때문에 LocalTime과 차이가 있을 수 있다. 시간대를 고려해야하는 경우 OffsetDateTime을 사용하는 것이 더 나은 선택일 수 있다.

Instant와 Date간의 변환
static Date from(Instant instant)	// Instant -> Date
Instant     toInstant()			// Date -> Instant​

 

4. LocalDateTIme과 ZonedDateTime

LocalDate와 LocalTime으로 LocalDateTime만들기

LocalDate date = LocalDate.of(2015, 12, 31);
LocalTime time = LocalTime.of(12, 34, 56);

LocalDateTime dt = LocalDateTime.of(date, time);
LocalDateTime dt2 = date.atTime(time);
LocalDateTime dt3 = time.atDate(date);
LocalDateTime dt4 = date.atTime(12, 34, 56);
LocalDateTime dt5 = time.atDate(2015, 12, 31);
LocalDateTime dt6 = date.atStartOfDay(); // dt6 = date.atTime(0, 0, 0);​

LocalDateTime에도 날짜와 시간을 직접 지정할 수 있는 다양한 버전의 of()와 now()가 있지만 위처럼 할 수 있다.

LocalDateTime의 변환
위와는 반대로 LocalDateTime을 LocalDate 또는 LocalTime으로 변환할 수 있다.

LocalDateTime dt = LocalDateTime.of(2015, 12, 31, 12, 34, 56);
LocalDate date = dt.toLocalDate();
LocalTime time = dt.toLocalTime();​


LocalDateTime으로 ZonedDateTime 만들기
LocalDateTime에 시간대를 추가하면 ZonedDateTime이 된다. 기존에는 TimeZone클래스로 시간대를 다루었지만 새로운 시간 패키지에서는 ZoneId라는 클래스를 사용한다. ZoneId는 일광 절약시간(DST, Daylight Saving Time)을 자동으로 처리해주어 편하다. LocalDateTime에 atZone()으로 시간대 정보를 추가하면 ZonedDateTIme을 얻을 수 있다.

ZoneId zid = ZoneId.of("Asia/Seoul");
ZonedDateTime zdt = dateTime.atZone(zid);

ZonedDateTime zdt2 = LocalDate.now().atStartOfDay(zid);

ZoneId nyId = ZoneId.of("America/New_York");
ZonedDateTime zdt3 = ZonedDatetime.now().withZoneSameInstant(nyId);​


ZoneOffSet
UTC로부터 얼마만큼 떨어져 있는지를 ZoneOffSet으로 표현한다. 서울은 +9로 UTC보다 9시간이 빠르다.

ZoneOffset krOffset = ZonedDateTime.now().getOffset();
ZoneOffset krOffset = ZoneOffset.of("+9"); // ±h, ±hh, ±hhmm, ±hh:mm
int krOffsetInSec = krOffset.get(ChronoField.OFFSET_SECONDS); // 32400초​


OffsetDateTime
ZonedDateTime은 ZoneId로 구역을 표현하는데, ZoneId가 아닌 ZoneOffset을 사용하는 것이 OffsetDateTime이다. ZoneOffset은 단지 시간대를 시간의 차이로만 구분한다.

ZonedDateTime zdt = ZonedDateTime.of(date, time, zid);
OffsetDateTime odt = OffsetDateTime.of(date, time, krOffset);

// ZonedDateTime -> OffsetDateTime
OffsetDateTime odt = zdt.toOffsetDateTime();​

ZonedDateTime의 변환
ZonedDateTime도 LocalDateTime처럼 날짜와 시간에 관련된 다른 클래스로 변환하는 메서드가 있다. GregorianCalendar와 가장 유사한 것이 ZonedDateTime이다.

// ZonedDateTime -> GregorianCalendar
GregorianCalendar from(ZonedDateTime zdt)

// GregorianCalendar -> ZonedDateTime
ZonedDateTime toZonedDateTime()​

 

5. TemporarlAdjusters

자주 쓰일만한 날짜 계산들을 대신 해주는 메서드를 정의해노흔 것이 TemporalAdjusters클래스이다.

LocalDate today = LocalDate.now();
LocalDate nextMonday =
	today.with(TemporalAdjusters.next(DayOfWeek.MONDAY);​


메서드 설명
 firstDayOfNextYear()  다음 해의 첫 날
 firstDayOfNextMonth()  다음 달의 첫 날
 firstDayOfYear()  올 해의 첫 날
 firstDayOfMonth()  이번 달의 첫 날
 lastDayOfYear()  올 해의 마지막 날
 lastDayOfMonth()  이번 달의 마지막 날
 firstInMonth                (DayOfWeek dayOfWeek)  이번 달의 첫 번째 ?요일
 lastInMonth                 (DayOfWeek dayOfWeek)  이번 달의 마지막 ?요일
 previous                       (DayOfWeek dayOfWeek)  지난 ?요일(당일 포함)
 previousOrSame         (DayOfWeek dayOfWeek)  지난 ?요일(당일 미포함)
 next                               (DayOfWeek dayOfWeek)  다음 ?요일(당일 미포함)
 nextOrSame                 (DayOfWeek dayOfWeek)  다음 ?요일(당일 포함)
 dayOfWeekInMonth    (int ordinal, DayOfWeek dayOfWeek)  이번 달의 n번째 ?요일

TemporalAdjuster 직접 구현하기
보통은 위의 표에 정의된 메서드로 충분하지만 필요하면 자주 사용하는 날짜계산을 해주는 메서드를 직접 만들 수 있다. LocalDate의 with()는 다음과 같이 정의되어 있으며, TemporalAdjuster인터페이스를 구현한 클래스의 객체를 매개변수로 제공해야한다.

LocalDate with(TemporalAdjuster adjuster)​

with()메서드는 대부분의 날짜와 시간에 관련된 클래스에 포함되어 있다. TemporalAdjuster인터페이스는 추상메서드 하나만 정의되어 있어서 이것만 구현하면 된다.

@FunctionalInterface
public interface TemporalAdjuster {
  Temporal adjustInto(Temporal temporal);
}​

실제로 구현해야하는 것은 adjustInto()지만, 우리가 TemporalAdjuster와 같이 사용해야 하는 메서드는 with()이다. with()와 adjustInto() 중에서 어느 쪽을 사용해도 되지만 adjustInto()는 내부적으로만 사용할 의도록 작성된 것이니 with()를 사용하도록 하자.

class DayAfterTomorrow implements TemporalAdjuster {
  @Override
  public Temporal adjustInto(Temporal temporal) {
    return temporal.plus(2, ChronoUnit.DAYS); // 2일을 더한다.
  }
}​

 

6. Period와 Duration

Period는 날짜의 차이를, Duration은 시간의 차이를 계산하기 위한 것이다.

between()
두 날짜 date1과 date2의 차이를 나타내는 Period는 between()으로 얻을 수 있다. 그리고 두 시간 time1과 time2의 차이 또한 Duration의 between()으로 얻을 수 있다. 첫 번째 매개변수가 두 번째 매개변수보다 이전이면 양수를 이후면 음수를 반환한다.

LocalDate date1 = LocalDate.of(2014, 1, 1);
LocalDate date2 = LocalDate.of(2015, 12, 31);

Period pe = Period.between(date1, date2);

LocalTime time1 = LocalTime.of(00, 00, 00);
LocalTime time2 = LocalTime.of(12, 34, 56);

Duration du = Duration.between(time1, time2);​

Period, Duration에서 특정 필드의 값을 얻을 때는 get()을 사용한다.

long year = pe.get(ChronoUnit.YEARS);
long month = pe.get(ChronoUnit.MONTHS);
long day = pe.get(ChronoUnit.DAYS);

long sec = du.get(ChronoUnit.SECONDS);
long nano = du.get(ChronoUnit.NANOS);​

Duration은 SECONDS와 NANOS밖에 사용하지 못해 불편하다. 시간, 분, 초를 구하기 위해서는 Duration을 LocalTime으로 변환하여 얻는 것이 간단하다.

LocalTime tmpTime = LocalTime.of(0,0).plusSeconds(du.getSeconds());
        
int hour = tmpTime.getHour();
...​


between()과 until()
until()은 between()과 거의 같은 일을 한다. 다만 between()은 static 메서드이고 until()은 인스턴스 메서드라는 차이가 있다.

Period pe = Period.between(today, myBirthDay);
Period pe = today.until(myBirthDay);
long dday = today.until(myBirthDay, ChronoUnit.DAYS);​

날짜가 아닌 시간에도 until()을 사용할 수 있지만 Duration을 반환하지는 않는다.

of(), with()
Period에는 of(), ofYears(), ofMonths(), ofWeeks(), ofDays()가 있고 Duration에는 of(), ofDays(), ofHours(), ofMinutes(), ofSeconds() 등이 있다. 특정 필드의 값을 변경하는 with()도 있다.

사칙연산, 비교연산, 기타 메서드
plus(), minus()외에 곱셈과 나눗셈을 위한 메서드가 있다.

pe = pe.minusYears(1).multipliedBy(2);
du = du.plusHours(1).dividedBy(60);​

단 Period에 나눗셈을 위한 메서드가 없다. 날짜의 기간을 표현하기 위한 것이기에 유용하지 않기 때문이다. 음수인지 확인하는 isNegative()와 0인지 확인하는 isZero()가 있다. 두 날짜 또는 시간을 비교할 때 사용하면 어느쪽이 앞인지 알 수 있다. 부호를 반대로 변경하는 negate()와 부호를 없애는 abs()도 존재한다. 다만 Period에는 abs()가 없다. Period에는 normalized()라는 메서드가 있는데 월의 값이 12를 넘지 않게 해준다. 예를 들면 1년 13개월을 2년 1개월로 바꿔준다.

다른 단위로 변환 - toTotalMonths(), toDays(), toHours(), toMinutes()
Period와 Duration을 다른 단위의 값으로 변환하는 데 사용된다. get()은 특정 필드의 값을 그대로 가져오지만 이 메서드들은 특정 단위로 변환한 결과를 반환한다는 차이가 있다.

클래스 메서드 설명
 Period  long toTotalMonths()  년월일을 월단위로 변환해서 반환(일 단위는 무시)
 Duration  long toDays()  일단위로 변환해서 반환
 long toHours()  시간단위로 변환해서 반환
 long toMinutes()  분단위로 변환해서 반환
 long toMillis()  천분의 일초 단위로 변환해서 반환
 long toNanos()  나노초 단위로 변환해서 반환

 

7. 파싱과 포맷

형식화(formatting)와 관련된 클래스들은 java.time.format패키지에 들어있다. 이 중 DateTimeFormatter가 핵심이다. 자주 사용되는 다양한 형식들이 정의되어 있고 필요하다면 직접 정의해서 사용도 가능하다.

LocalDate date = LocalDate.of(2016, 1, 2);
String yyyymmdd =
	DateTimeFormatter.ISO_LOCAL_DATE.format(date);
    
String yyyymmdd =
	date.format(DateTimeFormatter.ISO_LOCAL_DATE);​

위처럼 format()을 사용하여 날짜와 시간을 형식화 한다. 같은 기능을 하니 둘중 하나를 골라서 사용하면 되겠다.

DateTimeFormatter 설명 보기
 ISO_DATE_TIME  Date and time with ZoneId  2011-12-03T10:15:30+01:00[Europe/Paris]
 ISO_LOCAL_DATE  ISO Local Date  2011-12-03
 ISO_LOCAL_TIME  Time without offset  10:15:30
 ISO_LOCAL_DATE_TIME  ISO Local Date and Time  2011-12-03T10:15:30
 ISO_OFFSET_DATE  ISO Date with offset  2011-12-03+01:00
 ISO_OFFSET_TIME  Time with offset  10:15:30+01:00
 ISO_OFFSET_DATE_TIME  Date Time with Offset  2011-12-03T10:15:30+01:00
 ISO_ZONED_DATE_TIME  Zoned Date Time  2011-12-03T10:15:30+01:00[Europe/Paris]
 ISO_INSTANT  Date and Time of an Instant  2011-12-03T10:15:30Z
 BASIC_ISO_DATE  Basic ISO date  20111203
 ISO_DATE  ISO Date with
 or without offset
 2011-12-03+01:00
 2011-12-03
 ISO_TIME  Time with
 or without offset
 10:15:30+01:00
 10:15:30
 ISO_ORDINAL_DATE  Year and day of year  2012-337
 ISO_WEEK_DATE  Year and Week  2012-W48-6
 RFC_1123_DATE_TIME  RFC 1123 / RFC 822  Tue, 3 Jun 2008 11:05:30 GMT

로케일에 종속된 형식화
DateTimeFormatter static 메서드 ofLocalizedDate(), ofLocalizedTime(), ofLocalizedDateTime()은 로케일(locale)에 종속적인 포맷터를 생성한다.

DateTimeFormatter formatter =
	DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
    
String shortFormat = formatter.format(LocalDate.now());​

FormatStyle의 종류에 따른 출력 형태는 다음과 같다.

FormatStyle 날짜 시간
 FULL  2015년 11월 28일 토요일  N/A
 LONG  2015년 11월 28일 (토)  오후 9시 15분 13초
 MEDIUM  2015. 11. 28  오후 9:15:13
 SHORT  15. 11. 28  오후 9:15

출력형식 직접 정의하기
DateTimeFormatter의 ofPattern()으로 원하는 출력형식을 직접 작성할 수 있다.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");​

출력형식에 사용되는 기호의 목록은 다음과 같다.
기호 의미 보기
 G  연대(BC, AD)  서기 또는 AD
 y 또는 u  년도  2015
 M 또는 L  월(1 ~ 12 또는 1월 ~ 12월)  11
 Q 또는 q  분기(quarter)  4
 w  년의 몇 번째 주 (1 ~ 53)  48
 W  월의 몇 번째 주 (1 ~ 5)  4
 D  년의 몇 번째 일(1 ~ 366)  332
 d  월의 몇 번째 일(1 ~ 31)  28
 F  월의 몇 번째 요일(1 ~ 5)  4
 E 또는 e  요일  토 또는 7
 a  오전 / 오후 (AM, PM)  오후
 H  시간(0 ~ 23)  22
 k  시간(1 ~ 24)  22
 K  시간(0 ~ 11)  10
 h  시간(1 ~ 12)  10
 m  분(0 ~ 59)  12
 s  초(0 ~ 59)  35
 S  천분의 일초(0 ~ 999)  7
 A  천분의 일초(그 날의 0시 0분 0초부터)  80263808
 n  나노초(0 ~ 999999999)  475000000
 N  나노초(그 날의 0시 0분 0초부터)  81069992000000
 V  시간대 ID (VV)  Asia/Seoul
 z  시간대(time-zone) 이름  KST
 O  지역화된 zone-offset  GMT+9
 Z  zone-offset  +0900
 X 또는 x  zone-offset(Z는 +00:00을 의미)  +09
 '  escape문자(특수문자 표현에 사용)  없음

문자열을 날짜와 시간으로 파싱하기
문자열을 날짜 또는 시간으로 변환하려면 static메서드 parse()를 사용하면 된다. 날짜와 시간을 표현하는데 사용되는 클래스에 대부분 이 메서드가 포함되어 있다. 오버로딩된 parse()메서드 중 두 가지가 자주 사용된다.

static LocalDateTime parse(CharSequence text)
static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter)

LocalDate date =
	LocalDate.parse("2016-01-02", DateTimeFormatter.ISO_LOCAL_DATE);​

자주 사용되는 기본적인 형식의 문자열은 ISO_LOCAL_DATE와 같은 형식화 상수를 사용하지 않고도 파싱이 가능하다. 또 ofPattern()을 이용해서도 파싱을 할 수 잇다.

LocalDate newDate = LocalDate.parse("2001-01-01");


DateTImeFormatter pattern =
	DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime endOfYear =
	LocalDateTime.parse("2015-12-31 23:59:59", pattern);​

 

개인적으로 10장은 정말 머리에도 잘 들어오지 않고 재미도 없어서 꾸역꾸역 읽고 정리하는 챕터였다. 정말정말 너무너무 재미없었다. 사용할 곳이 생길 수도 있으니.. 정리했다.

728x90
반응형

'Study > JAVA' 카테고리의 다른 글

[Java] 11. 컬렉션 프레임웍(2)  (0) 2022.09.30
[Java] 11. 컬렉션 프레임웍(1)  (2) 2022.09.27
[Java] 10-1, 2. 날짜와 시간 & 형식화  (0) 2022.09.16
[Java] 9-2. 유용한 클래스  (0) 2022.09.14
[Java] 9-1. java.lang패키지  (0) 2022.09.13

댓글