본문 바로가기
java/java8

Date/Time

by iskull 2021. 11. 22.
728x90

 java8에서 새로 나온 날짜와 시간을 나타내는 api이다. 기존에 사용했던 Date, Calendar, SimpleDateFormat은 여러 불편함이 존재한다. 예를 들어 이름이 명확하지 않다.

  Date의 경우 날짜 뿐만 아니라 time stamp도 나타낼 수 있다. 또 한 Date.getTIme()은 일상적으로 사용하는 시간이 아닌 1970년 1월 1일 0시 0분 0초를 기준으로 현재시간을 뺀 값을 밀리세컨드 단위로 보여준다. 또 한 객체가 mutable하기 때문에 Date.setTime()을 통해 시간을 바꿀 수 있다. 따라서 thread-safe하지 않다.

  GregorianCalendar의 경우 type-safe하지 않다는 문제가 발생한다. GregorianCalendar는 연도, 월, 날짜를 인자로 넘겨서 인스턴스를 생성할 수 있는데 달이 0부터 시작한다. 따라서 임의의 수를 직접 넘기는 것이 아닌 enum을 사용해 넘겨야 한다. 또 한 연도, 달, 일을 int로 받기 때문에 음수가 들어올 가능성 또한 존재한다.

  이런 문제를 해결하기 위해 Joda-Time을 사용했었고 java8에서 표준으로 들어오게 되었다.

  java8에서 추가된 Date, Time은 크게 기계용 시간(machine time), 인류용 시간(human time)으로 나눌 수 있다.  기계용 시간은 EPOCK(1970-1-1, 0시0분0초)부터 밀리세컨드단위로, human time은 실생활에서 사용하는 단위로 나온다. 

 

API 사용 예제

  Instant는 기계용 시간을 계산할때 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {
    //machine time사용
    Instant machineTime = Instant.now();
    System.out.println(machineTime); // 기준시 UTC, GMT를 기준으로 시간이 나온다.
    System.out.println(machineTime.atZone(ZoneId.of("UTC")));
 
    //자신이 속한 시간대를 가져와서
    ZoneId zone = ZoneId.systemDefault();
    System.out.println(zone);
    //GMT 기준 시간이 아닌 자신이 속한 시간대의 시간으로 구한다.
    ZonedDateTime zonedDateTime = machineTime.atZone(zone);
    System.out.println(zonedDateTime);
 
}
cs

  LocalDateTIme은 현재 시스템이 위치한 time zone을 기준으로 human time을 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
    //human time 사용        
    //현재 시스템이 있는 local zone의 시간이 찍힌다
    //즉, 서버가 다른 local zone에 있으면 그 나라의 시간을 가져온다.
    LocalDateTime humanTime = LocalDateTime.now();
    System.out.println(humanTime);
 
    //시간과 날짜를 지정해서 만들 수 도 있다.
    LocalDateTime birthDay =
            LocalDateTime.of(1999, Month.MARCH, 28000);
    System.out.println(birthDay);
}
cs

  Time zone을 지정해서 특정 time zone의 현재 시간은 다음과 같이 구할 수 있다.

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
    //zone id를 사용해 특정 time zone의 현재 시간을 알아낸다.
    ZonedDateTime nowInKorea = ZonedDateTime.now(ZoneId.of("Asia/Seoul"));
    System.out.println(nowInKorea);
 
    //다음과 같은 방식을 사용하면 위와 같은 값을 구할 수 있다.
    Instant nowInstant = Instant.now();
    ZonedDateTime zonedDateTime = nowInstant.atZone(ZoneId.of("Asia/Seoul"));
    System.out.println(zonedDateTime);
}
cs

  시간을 비교해 기간 정하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 public static void main(String[] args) {
    LocalDate today = LocalDate.now();
    LocalDate thisYearBirthDay = LocalDate.of(2021, Month.MARCH, 28);
 
    //human time을 비교
    Period period = Period.between(today, thisYearBirthDay);
    System.out.println(period.getDays());
 
    Period util = today.until(thisYearBirthDay);
    System.out.println(util.get(ChronoUnit.DAYS));
 
    //machine time을 비교
    Instant now = Instant.now();
    Instant plus = now.plus(10, ChronoUnit.SECONDS);
    Duration between = Duration.between(now, plus);
    System.out.println(between.getSeconds());
}
cs
formatting, parsing
  formatting을 사전에 정의된 형식 할 수도 있다.
1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
    LocalDateTime now = LocalDateTime.now();
 
    DateTimeFormatter MMddyyyy = DateTimeFormatter.ofPattern("MM/dd/yyy");
    System.out.println(now.format(MMddyyyy));//11/22/2021
 
    LocalDate parse = LocalDate.parse("07/15/1982", MMddyyyy);
    System.out.println(parse);//1982-07-15
}
cs

java8에서 추가된 Time, Date관련 API는 이전 API와 호환된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public static void main(String[] args) {
    // Date -> Instant
    Date date = new Date();
    Instant instant = date.toInstant();
    // Instant -> Date
    Date newDate = Date.from(instant);
    System.out.println(newDate);
 
    //GregorianCalendar -> ZonedDateTime
    GregorianCalendar gregorianCalendar = new GregorianCalendar();
    ZonedDateTime dateTime = gregorianCalendar.toInstant()
            .atZone(ZoneId.systemDefault());
    System.out.println(dateTime);
 
    //GregorianCalendar -> LocalDateTime
    LocalDateTime localDateTime = gregorianCalendar.toInstant()
            .atZone(ZoneId.systemDefault())
            .toLocalDateTime();
    System.out.println(localDateTime);
 
    // ZonedDateTime -> GregorianCalendar
    ZonedDateTime zonedDateTime = gregorianCalendar.toInstant()
            .atZone(ZoneId.systemDefault());
    GregorianCalendar from = GregorianCalendar.from(zonedDateTime);
    System.out.println(from);
 
    // ZoneId -> TimeZone
    ZoneId zoneId = TimeZone.getTimeZone("PST")
            .toZoneId();
    System.out.println(zoneId);
 
    // TimeZone -> ZoneId
    TimeZone timeZone = TimeZone.getTimeZone(zoneId);
    System.out.println(timeZone);
 
}
cs

'java > java8' 카테고리의 다른 글

Concurrent programming  (0) 2021.11.22
optional  (0) 2021.11.22
stream  (0) 2021.11.21
interface의 default method와 static method  (0) 2021.11.20
함수형 인터페이스와 람다 표현식  (0) 2021.11.20