1. Date 클래스

공식 문서

docs.oracle.com/javase/8/docs/api/java/util/Date.html

 

Date (Java Platform SE 8 )

The class Date represents a specific instant in time, with millisecond precision. Prior to JDK 1.1, the class Date had two additional functions. It allowed the interpretation of dates as year, month, day, hour, minute, and second values. It also allowed t

docs.oracle.com

public class Date
extends Object
implements Serializable, Cloneable, Comparable<Date>

The class Date represents a specific instant in time, with millisecond precision.
Prior to JDK 1.1, the class Date had two additional functions. It allowed the interpretation of dates as year, month, day, hour, minute, and second values. It also allowed the formatting and parsing of date strings. Unfortunately, the API for these functions was not amenable to internationalization. As of JDK 1.1, the Calendar class should be used to convert between dates and time fields and the DateFormat class should be used to format and parse date strings. The corresponding methods in Date are deprecated.

JDK 1.1 이전에는 Date 클래스를 사용했지만, 1.1에 추가된 Calendar 클래스를 사용해서 잘 사용하지 않는다.(deprecated)

그래도 써보자

import java.util.Date;
import org.junit.jupiter.api.Test;

public class DateTest {

  @Test
  public void simpleDateTest() {
    Date date = new Date();
    System.out.println(date.toString());
  }
}

//결과 : Sat Oct 31 15:34:04 KST 2020

 getTime, getDate.. 등 메서드를 사용해보려했는데 대부분 deprecated라 그냥 넘어간다.


2. Calendar 클래스

공식 문서

https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html

 

Calendar (Java Platform SE 7 )

Adds or subtracts (up/down) a single unit of time on the given time field without changing larger fields. For example, to roll the current date up by one day, you can achieve it by calling: roll(Calendar.DATE, true). When rolling on the year or Calendar.YE

docs.oracle.com

public abstract class Calendar
extends Object
implements Serializable, Cloneable, Comparable<Calendar>

The Calendar class is an abstract class that provides methods for converting between a specific instant in time and a set of calendar fields such as YEAR, MONTH, DAY_OF_MONTH, HOUR, and so on, and for manipulating the calendar fields, such as getting the date of the next week. An instant in time can be represented by a millisecond value that is an offset from the Epoch, January 1, 1970 00:00:00.000 GMT (Gregorian).

The class also provides additional fields and methods for implementing a concrete calendar system outside the package. Those fields and methods are defined as protected.

Like other locale-sensitive classes, Calendar provides a class method, getInstance, for getting a generally useful object of this type. Calendar's getInstance method returns a Calendar object whose calendar fields have been initialized with the current date and time: Calendar rightNow = Calendar.getInstance();

A Calendar object can produce all the calendar field values needed to implement the date-time formatting for a particular language and calendar style (for example, Japanese-Gregorian, Japanese-Traditional). Calendar defines the range of values returned by certain calendar fields, as well as their meaning. For example, the first month of the calendar system has value MONTH == JANUARY for all calendars. Other values are defined by the concrete subclass, such as ERA. See individual field documentation and subclass documentation for details.

static field로 year, month, date, dateOfWeek등이 있고, get() 메서드를 통해 년, 월, 일 등을 호출할 수 있다. 추상 클래스이기 때문에 new Calendar()로 선언할 수 없고, 내부 메서드인 getInstance()를 통해 선언할 수 있다.

예제

www.codewars.com/kata/56eb0be52caf798c630013c0

 

Codewars: Achieve mastery through challenge

Codewars is where developers achieve code mastery through challenge. Train on kata in the dojo and reach your highest potential.

www.codewars.com

년을 입력으로 해당 해에 13일 금요일이 몇번 있는지 계산하는 문제이다. Calendar클래스를 통해 구해보자

import java.util.Calendar;

public class Kata {

  public static int unluckyDays(int year) {
    Calendar cal = Calendar.getInstance();
   
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.DATE, 13);
    int unluckyCount = 0;
    
    for (int month = 0; month < 12; month++) {
      cal.set(Calendar.MONTH, month);
      int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
      if(dayOfWeek == 6) {
        unluckyCount++;
      }
    }
    return unluckyCount;
  }
}

 getInstance() 메서드로 선언 후, 년과, 일을 set()메서드로 설정한다. 그 후에 반복문을 통해 month를 0~11까지 옮겨가며 13일이 금요일인지 확인하고 금요일이 맞다면 count를 1 증가시켜준다.

문제를 풀어보니 감이 오긴하는데, year과 date는 그대로 사용하는데 month는 0을 입력해야 1월, 1을 입력해야 2월... 이런식이기 때문에 좀 헷갈린다. 


3. Date, Calendar 클래스의 문제점

애매한 상수

날짜 연산을 컴파일 시점에서 오류를 확인 할 수 없다

Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONDAY, 1) // 월요일 하루를 더하는건가?

 

월 계산

위에서 본 것 처럼 Calendar 월 표기는 0이 1월, 11이 12월이다.

    /**
     * Value of the {@link #MONTH} field indicating the
     * first month of the year in the Gregorian and Julian calendars.
     */
    public final static int JANUARY = 0;

    /**
     * Value of the {@link #MONTH} field indicating the
     * second month of the year in the Gregorian and Julian calendars.
     */
    public final static int FEBRUARY = 1;

    /**
     * Value of the {@link #MONTH} field indicating the
     * third month of the year in the Gregorian and Julian calendars.
     */
    public final static int MARCH = 2;

그냥 1 빼주면 되지않나? 라고 생각할 수 도 있는데, 그걸 알지 못하고 사용하면 매우 불편함

 

불변(immutable)객체가 아니다.

set()메서드로 얼마든지 수정이 가능하다. 크게 문제가 되나? 생각할 수도 있는데 다른 코드에서도 공유한다면 한 쪽에서 변경한 값이 전체에 영향을 줄 수도 있다. 그리고 멀티쓰레드 환경에서 안전하지 못하다.

 

윤달을 고려하지않음


4. 그러면? (+ 뇌피셜)

자바에서 시간과 날짜를 계산하기 위해 제공하는 API가 있다. 대표적으로 Date와 Calendar인데, 평소에 나도 자주 사용하고, 날짜와 시간을 구할 일이 있을 때, 구글 검색을 해보면 대부분 Date, Calendar API사용에 대해 나온다. 

그런데 Date 클래스는 JDK 1.0, Calendar 클래스는 JDK 1.1부터 사용되었기 때문에 상당히 구식이고 문제점이 많다고 한다. 그래서 JDK 1.8이전에는 대부분 Joda-Time이라는 오픈소스 라이브러리를 사용한다고 한다. 

이를 잘 반영했는지 JDK 1.8부터는 Time 패키지의 LocalTime, LocalDate, LocalDateTime 등 개선된 클래스를 제공한다.

Date 클래스와 Calendar 간략하게만 알아봤는데, JDK 1.8에서 제공하는 Time 패키지를 더 공부하는게 나을것 같다. 더 간편하고 안전하다고 한다.

+ Recent posts