본문 바로가기
프로그래밍/JAVA

초보 자바 프로그래밍(44) - 날짜와 시간 처리 (문자열 포맷팅)

by 머니테크리더 2023. 5. 4.
반응형

날짜와 시간 처리 대표 이미지
날짜와 시간 처리 대표 이미지

🔖 INDEX

     

     

    자바에서 날짜와 시간을 처리하는 데는 주로 java.time 패키지를 사용합니다. 이 패키지는 자바 8부터 도입된 새로운 날짜와 시간 API로, 기존의 java.util.Date와 java.util.Calendar 클래스의 문제점을 해결하고자 개발되었습니다.

     

    java.time 패키지의 주요 클래스는 다음과 같습니다.

    • LocalDate: 날짜 정보만을 포함합니다.
    • LocalTime: 시간 정보만을 포함합니다.
    • LocalDateTime: 날짜와 시간 정보를 함께 포함합니다.
    • ZonedDateTime: 날짜와 시간 정보와 함께 시간대 정보까지 포함합니다.

    날짜와 시간 생성

    현재 날짜와 시간 얻기

    자바에서 현재 날짜와 시간을 얻으려면 다음과 같이 작성합니다.

    import java.time.LocalDate;
    import java.time.LocalTime;
    import java.time.LocalDateTime;
    import java.time.ZonedDateTime;
    import java.time.ZoneId;
    
    // 아래 출력 값은 실행 시점에 따라서 다릅니다.
    
    // 현재 날짜 생성
    LocalDate date = LocalDate.now();
    // 출력: 2023-04-26
    
    // 현재 시간 생성
    LocalTime time = LocalTime.now();
    // 출력: 14:30:45.123456789
    
    // 현재 날짜와 시간 생성
    LocalDateTime dateTime = LocalDateTime.now();
    // 출력: 2023-04-26T14:30:45.123456789
    
    // 현재 시간대의 날짜와 시간 생성
    ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.systemDefault());
    // 출력: 2023-04-26T14:30:45.123456789+09:00[Asia/Seoul]

     

    특정 날짜와 시간 생성하기

    특정 날짜와 시간을 생성하려면 다음과 같이 작성합니다.

    // 특정 날짜 생성 (2022년 1월 1일)
    LocalDate specificDate = LocalDate.of(2022, 1, 1);
    // 출력: 2022-01-01
    
    // 특정 시간 생성 (12시 30분 45초)
    LocalTime specificTime = LocalTime.of(12, 30, 45);
    // 출력: 12:30:45
    
    // 특정 날짜와 시간 생성 (2022년 1월 1일 12시 30분 45초)
    LocalDateTime specificDateTime = LocalDateTime.of(2022, 1, 1, 12, 30, 45);
    // 출력: 2022-01-01T12:30:45
    
    // 특정 시간대의 날짜와 시간 생성 (2022년 1월 1일 12시 30분 45초, 뉴욕 시간대)
    ZonedDateTime specificZonedDateTime = ZonedDateTime.of(2022, 1, 1, 12, 30, 45, 0, ZoneId.of("America/New_York"));
    // 출력: 2022-01-01T12:30:45-05:00[America/New_York]

     

     

    타임스탬프 생성하기

    Instant 클래스를 사용하여 현재 시점의 타임스탬프를 생성하거나 특정 시점의 타임스탬프를 생성할 수 있습니다. Instant.now() 메서드를 사용하면 현재 시점의 타임스탬프를 얻을 수 있고, Instant.ofEpochSecond(epochSecond) 메서드를 사용하여 특정 시점의 타임스탬프를 생성할 수 있습니다. 이를 통해 시간대에 영향을 받지 않는 일관된 시간 표현을 사용할 수 있습니다.

    import java.time.Instant;
    
    // 현재 시점의 타임스탬프 생성
    Instant currentTimestamp = Instant.now();
    // 출력: 2023-04-26T05:30:45.123456789Z (실제 출력값은 실행 시점에 따라 다릅니다.)
    
    // 특정 시점의 타임스탬프 생성 (유닉스 타임스탬프 1,000,000,000초)
    Instant specificTimestamp = Instant.ofEpochSecond(1000000000);
    // 출력: 2001-09-09T01:46:40Z

     

    Year, YearMonth, MonthDay

    Year, YearMonth, MonthDay 클래스는 각각 연도, 연-월, 월-일 정보를 표현하기 위한 클래스입니다. 이들 클래스를 사용하면 특정 정보만을 포함하는 날짜 표현을 처리할 수 있습니다.

    import java.time.Year;
    import java.time.YearMonth;
    import java.time.MonthDay;
    
    Year year = Year.of(2023);
    YearMonth yearMonth = YearMonth.of(2023, 4);
    MonthDay monthDay = MonthDay.of(4, 26);

     

    날짜와 시간 정보 가져오기

    날짜와 시간 정보를 가져오려면 다음과 같이 작성합니다.

    import java.time.LocalDate;
    import java.time.LocalTime;
    import java.time.LocalDateTime;
    
    // LocalDate 객체 생성 (예: 2023년 4월 26일)
    LocalDate date = LocalDate.of(2023, 4, 26);
    
    // 날짜 정보 얻기
    int year = date.getYear(); // 년도를 얻습니다.
    // 출력: 2023
    int month = date.getMonthValue(); // 월 (1-12)을 얻습니다.
    // 출력: 4
    int day = date.getDayOfMonth(); // 일 (1-31)을 얻습니다.
    // 출력: 26
    
    // LocalTime 객체 생성 (예: 14시 30분)
    LocalTime time = LocalTime.of(14, 30);
    
    // 시간 정보 얻기
    int hour = time.getHour(); // 시간 (0-23)을 얻습니다.
    // 출력: 14
    int minute = time.getMinute(); // 분 (0-59)을 얻습니다.
    // 출력: 30
    int second = time.getSecond(); // 초 (0-59)을 얻습니다.
    // 출력: 0
    
    // LocalDateTime 객체 생성 (예: 2023년 4월 26일 14시 30분)
    LocalDateTime dateTime = LocalDateTime.of(date, time);
    
    // 날짜와 시간 정보 얻기
    year = dateTime.getYear(); // 년도를 얻습니다.
    // 출력: 2023
    month = dateTime.getMonthValue(); // 월 (1-12)을 얻습니다.
    // 출력: 4
    day = dateTime.getDayOfMonth(); // 일 (1-31)을 얻습니다.
    // 출력: 26
    hour = dateTime.getHour(); // 시간 (0-23)을 얻습니다.
    // 출력: 14
    minute = dateTime.getMinute(); // 분 (0-59)을 얻습니다.
    // 출력: 30
    second = dateTime.getSecond(); // 초 (0-59)을 얻습니다.
    // 출력: 0

    해당 날짜의 요일을 가져오려면 다음과 같이 작성합니다.

    import java.time.LocalDate;
    import java.time.DayOfWeek;
    
    // 요일 확인
    LocalDate date = LocalDate.of(2022, 1, 1);
    DayOfWeek dayOfWeek = date.getDayOfWeek();
    // 출력: SATURDAY

     

     

    날짜와 시간 연산 및 비교

    날짜와 시간 연산

    날짜와 시간에 대한 연산을 수행하려면 다음과 같이 작성합니다.

    import java.time.LocalDate;
    import java.time.LocalTime;
    import java.time.LocalDateTime;
    import java.time.ZonedDateTime;
    import java.time.ZoneId;
    import java.time.temporal.ChronoUnit;
    
    // LocalDate 객체 생성 (예: 2023년 4월 26일)
    LocalDate date = LocalDate.of(2023, 4, 26);
    
    // 날짜 연산 수행
    LocalDate dateAfter3Days = date.plusDays(3); // 3일 후의 날짜를 얻습니다.
    // 출력: 2023-04-29
    LocalDate dateBefore2Months = date.minusMonths(2); // 2개월 전의 날짜를 얻습니다.
    // 출력: 2023-02-26
    
    // LocalTime 객체 생성 (예: 14시 30분)
    LocalTime time = LocalTime.of(14, 30);
    
    // 시간 연산 수행
    LocalTime timeAfter45Mins = time.plusMinutes(45); // 45분 후의 시간을 얻습니다.
    // 출력: 15:15
    LocalTime timeBefore2Hours = time.minusHours(2); // 2시간 전의 시간을 얻습니다.
    // 출력: 12:30
    
    // LocalDateTime 객체 생성 (예: 2023년 4월 26일 14시 30분)
    LocalDateTime dateTime = LocalDateTime.of(date, time);
    
    // 날짜와 시간 연산 수행
    LocalDateTime dateTimeAfter5Days3Hours = dateTime.plusDays(5).plusHours(3); // 5일 후 3시간 후의 날짜와 시간을 얻습니다.
    // 출력: 2023-05-01T17:30
    
    // ZonedDateTime 객체 생성 (예: 서울 시간대 2023년 4월 26일 14시 30분)
    ZonedDateTime zonedDateTime = ZonedDateTime.of(dateTime, ZoneId.of("Asia/Seoul"));
    
    // 날짜와 시간 연산 수행
    ZonedDateTime zonedDateTimeAfter7Days12Hours = zonedDateTime.plusDays(7).plusHours(12); // 7일 후 12시간 후의 날짜와 시간을 얻습니다.
    // 출력: 2023-05-03T02:30+09:00[Asia/Seoul]
    
    // ZonedDateTime에서 plus 메서드를 사용하여 날짜와 시간 연산 수행
    ZonedDateTime zonedDateTimeAfter3Days = zonedDateTime.plus(3, ChronoUnit.DAYS); // 3일 후의 날짜와 시간을 얻습니다.
    // 출력: 2023-04-29T14:30+09:00[Asia/Seoul]
    ZonedDateTime zonedDateTimeAfter90Minutes = zonedDateTime.plus(90, ChronoUnit.MINUTES); // 90분 후의 날짜와 시간을 얻습니다.
    // 출력: 2023-04-26T16:00+09:00[Asia/Seoul]
    
    // 다양한 날짜와 시간 단위로 연산을 수행할 수 있습니다.
    ZonedDateTime zonedDateTimeAfter5Hours = zonedDateTime.plus(5, ChronoUnit.HOURS); // 5시간 후의 날짜와 시간을 얻습니다.
    // 출력: 2023-04-26T19:30+09:00[Asia/Seoul]
    ZonedDateTime zonedDateTimeAfter2Weeks = zonedDateTime.plus(2, ChronoUnit.WEEKS); // 2주 후의 날짜와 시간을 얻습니다.
    // 출력: 2023-05-10T14:30+09:00[Asia/Seoul]

    또한, 날짜와 시간의 일부를 변경하기 위해 withXXX(value) 메서드를 사용할 수 있습니다. 여기서 XXX 은 변경하려는 날짜 및 시간의 부분(년, 월, 일, 시, 분, 초 등)을 나타냅니다. 이 메서드는 원본 객체를 변경하지 않고 새로운 객체를 반환합니다.

    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    
    // 날짜의 일부 변경
    LocalDate date = LocalDate.of(2022, 1, 1);
    LocalDate updatedDate = date.withYear(2023).withMonth(4).withDayOfMonth(26);
    // 출력: 2023-04-26
    
    // 시간의 일부 변경
    LocalTime time = LocalTime.of(12, 30);
    LocalTime updatedTime = time.withHour(14).withMinute(0);
    // 출력: 14:00
    
    // 날짜와 시간의 일부 변경
    LocalDateTime dateTime = LocalDateTime.of(2022, 1, 1, 12, 30);
    LocalDateTime updatedDateTime = dateTime.withYear(2023).withMonth(4).withDayOfMonth(26).withHour(14).withMinute(0);
    // 출력: 2023-04-26T14:00

     

    날짜와 시간 비교

    날짜와 시간을 비교하려면 다음과 같이 작성합니다.

    import java.time.LocalDate;
    import java.time.LocalTime;
    import java.time.LocalDateTime;
    import java.time.ZonedDateTime;
    import java.time.ZoneId;
    
    // LocalDate 객체 생성 (예: 2023년 4월 26일, 2023년 5월 1일)
    LocalDate date1 = LocalDate.of(2023, 4, 26);
    LocalDate date2 = LocalDate.of(2023, 5, 1);
    
    // LocalDate 비교
    boolean isDate1BeforeDate2 = date1.isBefore(date2); // date1이 date2보다 이전인지 확인합니다.
    // 출력: true
    boolean isDate1AfterDate2 = date1.isAfter(date2); // date1이 date2보다 이후인지 확인합니다.
    // 출력: false
    boolean isDate1EqualDate2 = date1.isEqual(date2); // date1이 date2와 같은 날짜인지 확인합니다.
    // 출력: false
    
    // LocalTime 객체 생성 (예: 14시 30분, 15시 45분)
    LocalTime time1 = LocalTime.of(14, 30);
    LocalTime time2 = LocalTime.of(15, 45);
    
    // LocalTime 비교
    boolean isTime1BeforeTime2 = time1.isBefore(time2); // time1이 time2보다 이전인지 확인합니다.
    // 출력: true
    boolean isTime1AfterTime2 = time1.isAfter(time2); // time1이 time2보다 이후인지 확인합니다.
    // 출력: false
    
    // LocalDateTime 객체 생성 (예: 2023년 4월 26일 14시 30분, 2023년 5월 1일 15시 45분)
    LocalDateTime dateTime1 = LocalDateTime.of(date1, time1);
    LocalDateTime dateTime2 = LocalDateTime.of(date2, time2);
    
    // LocalDateTime 비교
    boolean isDateTime1BeforeDateTime2 = dateTime1.isBefore(dateTime2); // dateTime1이 dateTime2보다 이전인지 확인합니다.
    // 출력: true
    boolean isDateTime1AfterDateTime2 = dateTime1.isAfter(dateTime2); // dateTime1이 dateTime2보다 이후인지 확인합니다.
    // 출력: false
    
    // ZonedDateTime 객체 생성 (예: 서울 시간대 2023년 4월 26일 14시 30분, 2023년 5월 1일 15시 45분)
    ZonedDateTime zonedDateTime1 = ZonedDateTime.of(dateTime1, ZoneId.of("Asia/Seoul"));
    ZonedDateTime zonedDateTime2 = ZonedDateTime.of(dateTime2, ZoneId.of("Asia/Seoul"));
    
    // ZonedDateTime 비교
    boolean isZonedDateTime1BeforeZonedDateTime2 = zonedDateTime1.isBefore(zonedDateTime2); // zonedDateTime1이 zonedDateTime2보다 이전인지 확인합니다.
    // 출력: true
    boolean isZonedDateTime1AfterZonedDateTime2 = zonedDateTime1.isAfter(zonedDateTime2); // zonedDateTime1이 zonedDateTime2보다 이후인지 확인합니다.
    // 출력: false

     

    날짜 간의 차이

    Period 클래스는 날짜 간의 차이를 표현합니다. Period를 사용하여 두 날짜 간의 차이를 구할 수 있습니다.

    import java.time.LocalDate;
    import java.time.Period;
    
    // LocalDate 객체 생성 (예: 2023년 4월 26일, 2023년 5월 15일)
    LocalDate date1 = LocalDate.of(2023, 4, 26);
    LocalDate date2 = LocalDate.of(2023, 5, 15);
    
    // Period 객체 생성 (두 날짜 간의 차이를 계산합니다)
    Period period = Period.between(date1, date2);
    
    // Period를 통한 날짜 차이 정보 얻기
    int yearsDiff = period.getYears(); // 년도 차이를 얻습니다.
    // 출력: 0
    int monthsDiff = period.getMonths(); // 월 차이를 얻습니다.
    // 출력: 0
    int daysDiff = period.getDays(); // 일 차이를 얻습니다.
    // 출력: 19
    
    // Period를 사용하여 날짜 연산 수행
    LocalDate dateAfterPeriod = date1.plus(period); // date1에 period를 더한 날짜를 얻습니다.
    // 출력: 2023-05-15
    LocalDate dateBeforePeriod = date2.minus(period); // date2에 period를 뺀 날짜를 얻습니다.
    // 출력: 2023-04-26

     

    시간 간의 차이

    Duration 클래스는 시간 간의 차이를 표현합니다. Duration을 사용하여 두 시간 간의 차이를 구할 수 있습니다.

    import java.time.Duration;
    import java.time.LocalDateTime;
    
    // LocalDateTime 객체 생성 (예: 2023년 4월 26일 14시 30분, 2023년 4월 27일 16시 45분)
    LocalDateTime dateTime1 = LocalDateTime.of(2023, 4, 26, 14, 30);
    LocalDateTime dateTime2 = LocalDateTime.of(2023, 4, 27, 16, 45);
    
    // Duration 객체 생성 (두 날짜와 시간 간의 차이를 계산합니다)
    Duration duration = Duration.between(dateTime1, dateTime2);
    
    // Duration을 통한 시간 차이 정보 얻기
    long daysDiff = duration.toDays(); // 일 차이를 얻습니다.
    // 출력: 1
    long hoursDiff = duration.toHours(); // 시간 차이를 얻습니다.
    // 출력: 26
    long minutesDiff = duration.toMinutes(); // 분 차이를 얻습니다.
    // 출력: 1575
    long secondsDiff = duration.getSeconds(); // 초 차이를 얻습니다.
    // 출력: 94500
    
    // Duration을 사용하여 날짜와 시간 연산 수행
    LocalDateTime dateTimeAfterDuration = dateTime1.plus(duration); // dateTime1에 duration을 더한 날짜와 시간을 얻습니다.
    // 출력: 2023-04-27T16:45
    LocalDateTime dateTimeBeforeDuration = dateTime2.minus(duration); // dateTime2에 duration을 뺀 날짜와 시간을 얻습니다.
    // 출력: 2023-04-26T14:30

     

    TemporalAdjusters

    TemporalAdjusters 클래스를 사용하여 날짜를 특정 기준으로 조정할 수 있습니다. TemporalAdjusters 에는 다양한 메서드들이 제공되며, 이를 활용하여 주어진 날짜를 원하는 기준으로 조정할 수 있습니다.

    import java.time.LocalDate;
    import java.time.temporal.TemporalAdjusters;
    
    LocalDate date = LocalDate.of(2022, 1, 1);
    
    // 해당 월의 첫 번째 일요일 찾기
    LocalDate firstSundayOfMonth = date.with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY));
    // 출력: 2022-01-02
    
    // 해당 월의 마지막 일요일 찾기
    LocalDate lastSundayOfMonth = date.with(TemporalAdjusters.lastInMonth(DayOfWeek.SUNDAY));
    // 출력: 2022-01-30
    
    // 다음 월의 첫 번째 월요일 찾기
    LocalDate firstMondayOfNextMonth = date.with(TemporalAdjusters.firstDayOfNextMonth()).with(TemporalAdjusters.next(DayOfWeek.MONDAY));
    // 출력: 2022-02-07

     

     

    날짜와 시간 포맷팅

    날짜와 시간을 문자열로 변환하거나 문자열로부터 날짜와 시간을 읽어오는 것을 포맷팅이라고 합니다. 자바에서 날짜와 시간의 포맷팅을 처리하는 데는 DateTimeFormatter 클래스를 사용합니다.

     

    날짜와 시간을 문자열로 변환하기

    날짜와 시간을 문자열로 변환하려면 다음과 같이 작성합니다.

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    
    // LocalDateTime 객체 생성 (예: 2023년 4월 26일 14시 30분)
    LocalDateTime dateTime = LocalDateTime.of(2023, 4, 26, 14, 30);
    
    // DateTimeFormatter 객체 생성 (원하는 포맷으로 날짜와 시간을 문자열로 변환합니다)
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일 HH시 mm분");
    
    // 날짜와 시간을 문자열로 변환하기
    String formattedDateTime = dateTime.format(formatter);
    // 출력: "2023년 04월 26일 14시 30분"
    
    // 주의: formatter의 패턴에 맞게 문자열로 변환됩니다.
    // 예를 들어, "yyyy년 M월 d일 H시 m분" 패턴으로 생성하면 "2023년 4월 26일

     

    문자열로부터 날짜와 시간 읽어오기

    문자열로부터 날짜와 시간을 읽어오려면 다음과 같이 작성합니다.

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.time.format.DateTimeParseException;
    
    // 문자열로부터 LocalDateTime 객체 읽어오기
    String strDateTime = "2023-04-26T14:30:00";
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
    
    try {
        LocalDateTime dateTime = LocalDateTime.parse(strDateTime, formatter);
        // 출력: 2023-04-26T14:30
    } catch (DateTimeParseException e) {
        // 문자열이 올바른 형식이 아닐 경우 예외 처리
        System.out.println("올바른 형식의 문자열이 아닙니다.");
    }

    DateTimeFormatter 클래스는 날짜와 시간 객체를 문자열로 변환하거나 문자열을 날짜와 시간 객체로 파싱하는 작업에 사용됩니다. DateTimeFormatter의 패턴은 날짜와 시간 객체의 각 요소를 특정한 형식으로 표현하는 방법을 정의합니다.

     

    패턴에서 사용되는 대표적인 문자들은 다음과 같습니다.

    1. 연도 (Year)
      • yyyy: 4자리 연도 (예: 2023)
      • yy: 2자리 연도 (예: 23)
    2. 월 (Month)
      • MM: 2자리 월 (예: 04)
      • M: 1자리 월 (예: 4)
      • MMMM: 전체 월 이름 (예: April)
      • MMM: 축약된 월 이름 (예: Apr)
    3. 일 (Day)
      • dd: 2자리 일 (예: 09)
      • d: 1자리 일 (예: 9)
    4. 시간 (Hour)
      • HH: 24시간제 2자리 시간 (예: 14)
      • H: 24시간제 1자리 시간 (예: 4)
      • hh: 12시간제 2자리 시간 (예: 02)
      • h: 12시간제 1자리 시간 (예: 2)
    5. 분 (Minute)
      • mm: 2자리 분 (예: 07)
      • m: 1자리 분 (예: 7)
    6. 초 (Second)
      • ss: 2자리 초 (예: 05)
      • s: 1자리 초 (예: 5)
    7. 나노초 (Nano)
      • nnnnnnnnn: 나노초 전체 (예: 123456789)
      • nnnnnn: 마이크로초 (예: 123456)
      • nnn: 밀리초 (예: 123)
    8. 오전/오후 (AM/PM)
      • a: 오전/오후 표시 (예: AM, PM)

     

    이 외에도 다양한 문자들이 있지만, 위에서 설명한 문자들은 대표적인 패턴 문자들입니다. 이 문자들을 조합하여 원하는 날짜 및 시간 포맷을 만들 수 있습니다. 예를 들어, "yyyy년 MM월 dd일 a hh시 mm분 ss초" 패턴을 사용하면 "2023년 04월 26일 오후 02시 30분 00초"와 같은 형식의 문자열로 변환됩니다.

     

    날짜와 시간에 대한 주의사항

    자바에서 날짜와 시간을 처리할 때 다음과 같은 주의사항을 염두에 두는 것이 좋습니다.

     

    윤초와 윤년

    윤초와 윤년은 날짜와 시간 처리에서 주의해야 할 사항입니다. 자바의 java.time 패키지는 이러한 복잡한 경우를 자동으로 처리해주므로, 새로운 날짜와 시간 API를 사용하는 것이 좋습니다.

     

    서머타임(Daylight Saving Time)

    일부 국가에서는 서머타임을 적용하여 시간대를 조정합니다. 이 경우에도 java.time 패키지를 사용하면 자동으로 처리됩니다. 그러나 시간대 변환 작업 시 서머타임 변동이 영향을 미칠 수 있으므로 주의해야 합니다.

     

    날짜와 시간 표현의 다양성

    다양한 국가와 문화권에서 날짜와 시간 표현 방식이 다를 수 있습니다. 이를 위해 자바의 DateTimeFormatter 클래스를 사용하여 다양한 형식의 날짜와 시간을 처리할 수 있습니다.

     

    이 글에서는 자바에서 날짜와 시간을 처리하는 방법에 대해 알아보았습니다. java.time 패키지를 사용하면 다양한 날짜와 시간 처리 작업을 수행할 수 있습니다.

    댓글