개발이야기/Java

[Java] LocalDateTime을 활용해서 날짜와 시간 처리하기

후린개발자 2024. 2. 13.
반응형

LocalDateTime 클래스는 날짜와 시간을 모두 포함하는 객체를 나타내며 시간대(time-zone) 정보 없이 날짜와 시간을 표현합니다.
Local이란 개념은 해당 날짜와 시간이 특정 지역의 시간대에 의존하지 않고, UTC를 기준으로 하여 시간을 저장하고 특정 지역의 시간대로 변환을 할 수 있습니다.

아래 소스코드는 LocalDateTime을 활용해서 메서드들을 통해 날짜 및 시간을 처리하고 시간대를 세팅하는 코드들입니다.

 

 

1. 메서드

-getDate: LocalDateTime에서 날짜 정보만 추출하고 시간 정보는 0으로 설정하여 리턴합니다.

-daysInMonth: 파라미터로 받은 날짜에 해당되는 달의 총일수를 리턴합니다. 윤년 여부를 고려하여 일 수를 계산합니다.

-beginningOfMonth: 파라미터로 받은 날짜에 해당되는 달의 첫 번째 날짜를 리턴합니다. 시간은 0시 0분 0초로 설정됩니다.

-endOfMonth: 파라미터로 받은 날짜에 해당되는 달의 마지막 날짜를 리턴합니다. 마지막 시간은 23시 59분 59초로 설정됩니다.

-toString: 파라미터로 받은 날짜를 지정된 패턴으로 포맷하여 문자열로 리턴합니다.

-toLocalDateTimeByOffset: 파라미터로 받은 날짜에 지정된 offset의 시간대를 적용하여 리턴합니다.

-utcBeginningOfDay: 파라미터로 받은 날짜를 UTC 시간대의 0시로 설정하고, 해당 offset의 시간대로 재설정한 날짜를 리턴합니다.

-utcEndOfDay: 현재 날짜에 파라미터로 받은 offset의 시간대(타임존)의 종료시간(23시 59분)을 UTC시간대로 리턴합니다.

-utcBeginningOfToday: 현재 날짜를 받아, 파라미터로 받은 offset의 시간대(타임존)의 시작시간(00시 00분)을 UTC시간대로 리턴합니다.

-localDateTimeToDate: 파라미터로 받은 LocalDateTime을 시스템의 기본 설정된 시간대를 사용하여 Date로 변환합니다.

-localDateToDate: 파라미터로 받은 LocalDate를 시스템의 기본 설정된 시간대를 사용하여 Date로 변환합니다.

-dateToLocalDateTime: 파라미터로 받은 Date를 시스템의 기본 설정된 시간대를 사용하여 LocalDateTime으로 변환합니다.

-getLocalDateTimeFromTicks: 파라미터로 받은 ticks값을 LocalDateTime으로 변환하여 리턴합니다.

-localBeginningOfDay: 파라미터로 받은 날짜를 UTC 시간대로 변환한 후, 파라미터로 받은 offset의 시간대를 적용하여 날짜의 0시를 리턴합니다.

 

 

2. 전체 소스코드

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class TEST {
    /**
     * getDate
     * <pre>
     * LocalDateTime에서 날짜만 추출
     * </pre>
     * @param localDateTime
     * @return
     */
    public static LocalDateTime getDate(LocalDateTime localDateTime) {
        return localDateTime.toLocalDate().atStartOfDay();
    }
    
    /**
     * daysInMonth
     * <pre>
     * 파라미터로 받은 날짜에 해당되는 달의 총 일수를 리턴한다.
     * </pre>
     * @param dateTime
     * @return
     */
    public static int daysInMonth(LocalDateTime dateTime) {
        return dateTime.getMonth().length(dateTime.toLocalDate().isLeapYear()); //isLeapYear은 윤년여부
    }
    
    /**
     * beginningOfMonth
     * <pre>
     * 파라미터로 받은 날짜에 해당되는 달의 첫번째 날짜를 리턴한다.
     * </pre>
     * @param dateTime
     * @return
     */
    public static LocalDateTime beginningOfMonth(LocalDateTime dateTime) {
        return LocalDateTime.of(dateTime.getYear(), dateTime.getMonth(), 1, 0, 0, 0);
    }
    
    /**
     * endOfMonth
     * <pre>
     * 파라미터로 받은 날짜에 해당되는 달의 마지막 날짜(23시 59분 99초)를 리턴한다.
     * </pre>
     * @param dateTime
     * @return
     */
    public static LocalDateTime endOfMonth(LocalDateTime dateTime) {
        return LocalDateTime.of(dateTime.getYear(), dateTime.getMonth(), daysInMonth(dateTime), 23, 59, 59, 999_999_999); 
    }
    
    
    /**
     * toString
     * <pre>
     * 파라미터로 받은 날짜를 파라미터로 받은 패턴으로 포맷하여 문자열로 리턴한다.
     * </pre>
     * @param dateTime
     * @param pattern
     * @return
     */
    public static String toString(LocalDateTime dateTime, String pattern) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
        return df.format(dateTime);
        
    }
    
    /**
     * toLocalDateTimeByOffset
     * <pre>
     * 파라미터로 받은 날짜를 파라미터로 받은 offset의 시간대를 적용하여 리턴한다.
     * </pre>
     * @param dateTime
     * @param offset
     * @return dateTime
     */
    public static LocalDateTime toLocalDateTimeByOffset(LocalDateTime dateTime, String offset) {
        
        ZoneOffset zoneOffset = ZoneOffset.of(offset);
        dateTime = dateTime.plusSeconds(zoneOffset.getTotalSeconds());

        return dateTime;
    }
    
    /**
     * utcBeginningOfDay
     * <pre>
     * 파라미터로 받은 날짜를 UTC 시간대의 0시로 셋팅하고 이 시간을 파라미터로 받은 offset의 시간대로 재설정한 날짜를 리턴한다.  
     * </pre>
     * @param localDateTime
     * @param offset
     * @return dateTime
     */
    public static LocalDateTime utcBeginningOfDay(LocalDateTime localDateTime, String offset) {
        LocalDateTime newLocalDateTime = getDate(localDateTime);
        
        Instant newInstant = newLocalDateTime.atZone(ZoneOffset.UTC).toInstant();
        long newTicks = (newInstant.getEpochSecond() + 62_135_596_800L) * 10_000_000 + newInstant.getNano() / 100;
        long offsetTicks = Long.valueOf(ZoneOffset.of(offset).getTotalSeconds()) * 10_000_000;
        
        newLocalDateTime = getLocalDateTimeFromTicks(newTicks + (offsetTicks * -1 ));

        return newLocalDateTime;
    }
    
    /**
     * utcEndOfDay
     * <pre>
     * 현재 날짜에 파라미터로 받은 offset의 시간대(타임존)의 종료시간(23시 59분)을 UTC시간대로 리턴한다.
     * ex) offset : +09:00(한국), 종료 시간 : 현재날짜 23시59분(KST) -> 현재날짜 14시59분(UTC)
     * </pre>
     * @param localDateTime
     * @param timeOffset
     * @return
     */
    public static LocalDateTime utcEndOfDay(LocalDateTime localDateTime, String timeOffset) {
        LocalDateTime newLocalDateTime = getDate(localDateTime);
     
        Instant newInstant = newLocalDateTime.atZone(ZoneOffset.UTC).toInstant();
        long newTicks = (newInstant.getEpochSecond() + 62_135_596_800L) * 10_000_000 + newInstant.getNano() / 100;
        long offsetTicks = Long.valueOf(ZoneOffset.of(timeOffset).getTotalSeconds()) * 10_000_000;
        long ticksPerDay = 864_000_000_000L;
        long ticksPerSecond = 10_000_000;
        
        newLocalDateTime = getLocalDateTimeFromTicks(newTicks + ticksPerDay - ticksPerSecond + (offsetTicks * -1 ));

        return newLocalDateTime;
    }
    
    /**
     * utcBeginningOfToday
     * <pre>
     * 현재날짜에, 파라미터로 받은 offset의 시간대(타임존)의 시작시간(00시 00분)을 UTC시간대로 리턴한다.
     * ex) offset :+09:00(한국), 시작 시간 : 현재날짜 00시(KST) -> 현재날짜 15시(UTC)
     * </pre>
     * @param timeOffset
     * @return
     */
    public static LocalDateTime utcBeginningOfToday(String timeOffset) {
        LocalDateTime newLocalDateTime = getDate(LocalDateTime.now(ZoneOffset.UTC));

        Instant newInstant = newLocalDateTime.atZone(ZoneOffset.UTC).toInstant();
        long newTicks = (newInstant.getEpochSecond() + 62_135_596_800L) * 10_000_000 + newInstant.getNano() / 100;
        long offsetTicks = Long.valueOf(ZoneOffset.of(timeOffset).getTotalSeconds()) * 10_000_000;
        
        newLocalDateTime = getLocalDateTimeFromTicks(newTicks + (offsetTicks * -1 ));

        return newLocalDateTime;
    }
    
    /**
     * localDateTimeToDate
     * <pre>
     * 파라미터로 받은 LocalDateTime 를 Date로 변환한다. (시간대는 현재 서버의 기본 설정된 시간대 사용.)
     * </pre>
     * @param localDateTime
     * @return
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneOffset.systemDefault()).toInstant());
    }
    
    /**
     * localDateToDate
     * <pre>
     * 파라미터로 받은 LocalDate 를 Date로 변환한다. (시간대는 현재 서버의 기본 설정된 시간대 사용.)
     * </pre>
     * @param localDateTime
     * @return
     */
    public static Date localDateToDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay(ZoneOffset.systemDefault()).toInstant());
    }
    
    
    /**
     * dateTimeToLocalDateTime
     * <pre>
     * 파라미터로 받은 Date를 LocalDateTime로 변환한다. (시간대는 현재 서버의 기본 설정된 시간대 사용.)
     * </pre>
     * @param localDateTime
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneOffset.systemDefault()).toLocalDateTime();
    }
    
    /**
     * getLocalDateTimeFromTicks
     * <pre>
     * 파라미터로 받은 ticks값을 LocalDateTime로 변환하여 리턴한다.
     * </pre>
     * @param ticks 100나노초(천만분의 1초)
     * @return
     */
    private static LocalDateTime getLocalDateTimeFromTicks(long ticks) {
        if (ticks < 0) {
            ticks = 0;
        } else {
            long maxTicks = 3_155_378_975_999_999_999L;
            if (ticks > maxTicks)
                ticks = maxTicks;
        }

        Instant instant = Instant.ofEpochSecond((ticks / 10_000_000) - 62_135_596_800L, (ticks % 10_000_000) * 100);
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

        return localDateTime;
    }
    
    
    /**
     * localBeginningOfDay
     * <pre>
     * 파라미터로 받은 날짜를 UTC 시간대로 변환 후 파라미터로 받은 offset의 시간대를 적용한 날짜의 0시를 리턴한다.
     * </pre>
     * @param utcDateTime
     * @param timeOffset
     * @return
     */
    public static LocalDateTime localBeginningOfDay(LocalDateTime dateTime, String timeOffset) {
        LocalDateTime newLocalDateTime;
    
        Instant utcInstant = dateTime.atOffset(ZoneOffset.UTC).toInstant();
        long utcDateTimeTicks = (utcInstant.getEpochSecond() + 62_135_596_800L) * 10_000_000 + utcInstant.getNano() / 100;
        long offsetTicks = Long.valueOf(ZoneOffset.of(timeOffset).getTotalSeconds()) * 10_000_000;
        newLocalDateTime = getLocalDateTimeFromTicks( utcDateTimeTicks + offsetTicks).toLocalDate().atStartOfDay();
      
        return newLocalDateTime;
    }
    public static void main(String[] args) throws Exception {
        // getDate 예제
        LocalDateTime dateTime = LocalDateTime.now();
        LocalDateTime dateOnly = getDate(dateTime);
        System.out.println("getDate 예제: " + dateOnly);

        // daysInMonth 예제
        int days = daysInMonth(dateTime);
        System.out.println("daysInMonth 예제: " + days);

        // beginningOfMonth 예제
        LocalDateTime beginningOfMonth = beginningOfMonth(dateTime);
        System.out.println("beginningOfMonth 예제: " + beginningOfMonth);

        // endOfMonth 예제
        LocalDateTime endOfMonth = endOfMonth(dateTime);
        System.out.println("endOfMonth 예제: " + endOfMonth);

        // toString 예제
        String pattern = "yyyy-MM-dd HH:mm:ss";
        String formattedDateTime = toString(dateTime, pattern);
        System.out.println("toString 예제: " + formattedDateTime);

        // toLocalDateTimeByOffset 예제
        String offset = "+09:00";
        LocalDateTime dateTimeWithOffset = toLocalDateTimeByOffset(dateTime, offset);
        System.out.println("toLocalDateTimeByOffset 예제: " + dateTimeWithOffset);

        // utcBeginningOfDay 예제
        String utcOffset = "+09:00";
        LocalDateTime utcBeginning = utcBeginningOfDay(dateTime, utcOffset);
        System.out.println("utcBeginningOfDay 예제: " + utcBeginning);

        // utcEndOfDay 예제
        String timeOffset = "+09:00";
        LocalDateTime utcEnd = utcEndOfDay(dateTime, timeOffset);
        System.out.println("utcEndOfDay 예제: " + utcEnd);

        // utcBeginningOfToday 예제
        LocalDateTime utcBeginningOfToday = utcBeginningOfToday(timeOffset);
        System.out.println("utcBeginningOfToday 예제: " + utcBeginningOfToday);

        // localDateTimeToDate 예제
        Date date = localDateTimeToDate(dateTime);
        System.out.println("localDateTimeToDate 예제: " + date);

        // localDateToDate 예제
        LocalDate localDate = LocalDate.now();
        Date convertedDate = localDateToDate(localDate);
        System.out.println("localDateToDate 예제: " + convertedDate);

        // dateToLocalDateTime 예제
        LocalDateTime convertedDateTime = dateToLocalDateTime(date);
        System.out.println("dateToLocalDateTime 예제: " + convertedDateTime);

        // localBeginningOfDay 예제
        LocalDateTime localBeginning = localBeginningOfDay(dateTime, timeOffset);
        System.out.println("localBeginningOfDay 예제: " + localBeginning);
    } 
}

 


Colsole 결과

반응형

댓글

💲 추천 글