자바 날짜 대 달력


364

누군가 현재의 "모범 사례" DateCalendar유형에 대해 조언 해 주시겠습니까 ?

새 코드를 작성할 때 항상 선호 Calendar하는 것이 가장 좋습니까 Date, 아니면 Date더 적합한 데이터 유형이있는 환경 이 있습니까?



2
참고로, 같은 귀찮은 된 날짜 - 시간 수업 java.util.Date, java.util.Calendar그리고 java.text.SimpleDateFormat에 의해 대체 지금 레거시, java.time의 클래스. 대부분의 java.time 기능은 ThreeTen-Backport 프로젝트 에서 Java 6 & Java 7로 백 포트됩니다 . ThreeTenABP 프로젝트 에서 이전 Android에 더 적합합니다 . ThreeTenABP 사용 방법…을 참조하십시오 .
Basil Bourque

2
참고로 Joda-Time 프로젝트 (다른 ​​의견에서 언급)는 이제 유지 관리 모드 에 있으며 팀은 java.time 클래스 로의 마이그레이션을 조언합니다 . Oracle의 Tutorial을 참조하십시오 .
Basil Bourque

답변:


377

날짜는 더 간단한 클래스이며 주로 이전 버전과의 호환성을 위해 존재합니다. 특정 날짜를 설정하거나 날짜를 산술해야하는 경우 달력을 사용하십시오. 캘린더는 현지화도 처리합니다. Date의 이전 날짜 조작 기능은 더 이상 사용되지 않습니다.

개인적으로 나는 선택이있을 때 긴 시간 (또는 적절하게 긴) 또는 달력으로 밀리 초 단위의 시간을 사용하는 경향이 있습니다.

Date와 Calendar는 모두 변경 가능하므로 API에서 사용할 때 문제가 발생하는 경향이 있습니다.


5
참고로, 같은 몹시 귀찮은 된 날짜 - 시간 수업 java.util.Date, java.util.Calendar그리고 java.text.SimpleDateFormat지금 기존 에 의해 대체, java.time의 나중에 자바 8에 내장 된 클래스. Oracle의 Tutorial 참조하십시오 .
Basil Bourque

67

새 코드를 작성하는 가장 좋은 방법은 (정책에서 타사 코드를 허용하는 경우) Joda Time 라이브러리 를 사용하는 것 입니다.

DateCalendar 모두 디자인 문제가 너무 많아서 새로운 코드를위한 좋은 솔루션이 아닙니다.


7
나는 joda 시간을 사용하라는 제안을 두 번째로합니다. 사용하기 쉽고 이해하기 쉬우 며 더 많은 기능을 사용할 수 있습니다.
Jeroen van Bergen

30
Joda Time을 사용할지 표준 JDK 클래스를 사용할 지에 대한 자세한 내용은 stackoverflow.com/questions/589870/…
Jonik

3
다운 보트 자격이 있는지는 모르겠지만 질문에 대답하지는 않습니다. 댓글로 더 나아질 수 있습니다.
IcedDante

7
질문은 단일 공급 업체 종속성 위험을 프로젝트에 추가하는 타사 라이브러리를 사용하지 않는 Date 및 Calendar 사용에 관한 것이기 때문입니다.
Archimedes Trajano

3
이것은 java.time 패키지 가 Java 8에서 사용 가능 해질 때까지 "가장 좋은 방법" 이었습니다.
DaBlick

58
  • Date그리고 Calendar정말 같은 기본 개념 (모두가 나타내고있는 시간 인스턴트를 하고 기초 주위에 래퍼 long값).

  • 요일과 시간과 같은 것들에 대한 구체적인 사실을 제공하는 것처럼 보이지만 Calendar실제로Date 는 그것 보다 훨씬 더 깨진 것이라고 주장 할 수 있습니다.timeZone 속성 하면 콘크리트가 블랑 망으로 변합니다! 이러한 이유로 인해 객체는 실제로 월-일 또는 시간 저장소로 유용하지 않습니다 .

  • 사용 Calendar주어 졌을 때, 계산기로 단지 DateTimeZone객체, 당신을 위해 계산을 할 것입니다. 응용 프로그램에서 속성 입력에 사용하지 마십시오.

  • 사용하다 SimpleDateFormat 과 함께 TimeZoneDate디스플레이 문자열을 생성 할 수 있습니다.

  • Joda-Time이 모험적이라고 생각되면 불필요하게 복잡한 IMHO이며 곧 JSR-310 날짜 API로 대체됩니다.

  • 나는 자신의 YearMonthDay클래스 를 굴리는 것이 어렵지 않다고 대답했다.이 클래스 Calendar는 날짜 계산을 위해 사용 됩니다. Joda-Time (및 JSR-310 )이 대부분의 유스 케이스에 대해 너무 복잡하기 때문에 제안에 대해 하향 투표를 받았지만 여전히 유효하다고 생각합니다 .


1
JSR310에는 시간 프레임이 있습니까? Java 7에있을 예정이지만 지금은 그렇지 않습니다.
Brian Agnew

@ 브라이언-메일 링리스트에서 확실히 조용히 갔다!
oxbow_lakes

확인 만하면 비활성 상태가되어 18 개월 안에 이정표 초안을 게시하지 않은 것입니다 :-(
Brian Agnew

메일 링리스트에 대한 가장 최근의 의견은 7 월과 Stephen에 의한 것이며 따라서 프로젝트는 여전히 똑딱 거리고 있습니다
oxbow_lakes

동의했다. Date를 불변 개체로 안전하게 사용하는 방법과 Calendar를 사용하여 날짜를 조작하는 방법을 알고 있다면 대부분의 사람들이 안전해야합니다. 다중 스레드 코드에서 SimpleDateFormat을 사용할 때는주의하십시오.
cwash

25

날짜는 날짜 개체를 저장하는 데 가장 좋습니다. 그것은 지속되는 것, 직렬화 된 것입니다 ...

달력은 날짜를 조작하는 데 가장 좋습니다.

참고 : Date는 변경 가능하므로 스레드로부터 안전하지 않기 때문에 Date보다 java.lang.Long을 선호하는 경우가 있습니다. Date 객체에서 setTime () 및 getTime ()을 사용하여 둘 사이를 전환합니다. 예를 들어, 응용 프로그램의 상수 날짜 (예 : 1970/01/01 0 또는 2099/12/31로 설정 한 적용 END_OF_TIME; null 값을 시작 시간 및 종료 시간으로 대체하는 데 특히 유용합니다. SQL이 널 (null)과 같이 고유하기 때문에 데이터베이스에 유지하는 경우).


나는 당신이 불변에 대해 가지고 있다고 생각합니다java.lang.Long
pjp

17

가능한 경우 일반적으로 Date를 사용합니다. 변경 가능하지만 실제로는 더 이상 사용되지 않습니다. 결국 기본적으로 날짜 / 시간을 나타내는 long을 감 쌉니다. 반대로 값을 조작 해야하는 경우 캘린더를 사용합니다.

이 방법으로 생각할 수 있습니다. toString () 메서드를 사용하여 쉽게 조작하고 문자열로 변환 할 수있는 문자열이 필요한 경우에만 StringBuffer를 사용합니다. 같은 방법으로, 나는 임시 데이터를 조작해야 할 경우에만 달력을 사용합니다.

모범 사례를 위해 도메인 모델 외부에서 가능한 한 불변의 객체를 사용하는 경향이 있습니다 . 부작용의 가능성을 크게 줄이고 JUnit 테스트 대신 컴파일러가 수행합니다. 개인 결승 을 만들어이 기술을 사용합니다클래스에서 필드를 .

그리고 StringBuffer 유추로 돌아갑니다. 다음은 달력과 날짜를 변환하는 방법을 보여주는 코드입니다.

String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String

// immutable date with hard coded format.  If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date =     new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");

// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);

// mutate the value
cal.add(Calendar.YEAR, 1);

// convert back to Date
Date newDate = cal.getTime();

// 
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);

예, 변경 불가능한 객체 는 날짜-시간 작업에 적합합니다. java.time의 대체 클래스 Date/ Calendar불변의 객체 패턴을 사용합니다.
Basil Bourque

그것은 사실이지만 2010 년에는 해당되지 않습니다.
Archimedes Trajano

예. 그러나 지금 까지 150,000 명 이상이이 페이지를 읽고있는 수천 명의 사람들이 있습니다. 내 의견은 당신에 대한 비판이 아니라 그들에 대한 메모입니다.
Basil Bourque

나는 그것이 다른 대답을 찬성하는 이유입니다. 그러나 여전히 위의 답변이 필요한 오래된 JDK로 고통 받아야하는 사람들이 있습니다.
Archimedes Trajano

1
실제로 Java 6 & 7의 경우 ThreeTen-Backport 프로젝트가 있습니다. 이것은 거의 동일한 API를 가진 대부분의 java.time 기능을 제공합니다. 따라서 끔찍한 레거시 날짜-시간 클래스를 사용할 필요가 없습니다.
Basil Bourque

15

Dates 불변 시점으로 사용되어야한다. Calendars는 변경 가능하며 다른 날짜와 협업하기 위해 다른 클래스와 협력해야하는 경우 전달 및 수정 될 수 있습니다. 에 그들과 유사 고려 String하고StringBuilder 당신은 나는 그들이 사용되어야한다 고려 방법을 이해하는 것입니다.

(그리고 예, Date는 실제로 기술적으로 변경 불가능하다는 것을 알고 있지만 의도는 변경 불가능해서는 안되며 더 이상 사용되지 않는 메소드를 호출하는 것이 없다면 그렇게하는 것입니다.)


예, 변경 불가능한 객체 는 날짜-시간 작업에 적합합니다. java.time의 대체 클래스 Date/ Calendar불변의 객체 패턴을 사용합니다. 특히을 Instant대체 java.util.Date하고 /를 ZonedDateTime대체합니다 . CalendarGregorianCalendar
Basil Bourque

15

tl; dr

현재의 "모범 사례"에 대해 조언 Date하고Calendar

항상 찬성 Calendar하는 것이 최선입니까?Date

이러한 레거시 클래스는 완전히 피하십시오 . 대신 java.time 클래스를 사용하십시오 .

  • UTC 로 잠시 사용 하십시오.Instant
    Date )
  • 특정의 순간 시간대 , 사용 (현대 상응하는 )ZonedDateTime
    GregorianCalendar
  • UTC에서 특정 오프셋 에서 잠시 동안 사용하십시오 (레거시 클래스에서는 동일하지 않음)OffsetDateTime
  • 시간대 또는 오프셋을 알 수없는 날짜-시간 (순간이 아님)의 경우 (레거시 클래스에서는 동일하지 않음)LocalDateTime

최신 및 기존 Java의 모든 날짜-시간 유형 표

세부

Ortomala 의해 답변을 Lokni 현대 사용하는 것이 좋습니다 할 권리 java.time에 오히려 귀찮은 오래된 기존의 날짜 - 시간 수업 (보다 클래스를 Date, Calendar등). 그러나 그 대답은 잘못된 클래스를 동등한 것으로 제안합니다 (해답에 대한 내 의견 참조).

java.time 사용

java.time 클래스는 레거시 날짜-시간 클래스 (야간 차이)에 비해 크게 개선되었습니다. 구식 수업은 잘 설계되지 않았고 혼란스럽고 번거 롭습니다. 가능할 때마다 이전 수업을 피해야합니다. 그러나 이전 / 새로 변환하거나 이전 / 새로 변환해야 할 때 새 메소드를 호출하여 이전에 추가 할 수 있습니다 클래스를 클래스에 .

변환에 대한 자세한 내용은 내 Answer and nifty 다이어그램 을 다른 질문으로 변환하십시오. java.util.Date를 "java.time"유형으로 변환 하시겠습니까?.

검색 스택 오버플로는 java.time 사용에 관한 수백 가지의 질문과 답변을 제공합니다. 그러나 여기에 간단한 시놉시스가 있습니다.

Instant

으로 현재 순간을 가져옵니다 Instant. 이 Instant클래스는 나노초 의 해상도 (소수점의 최대 9 자리)로 UTC 의 타임 라인에서 순간을 나타냅니다 .

Instant instant = Instant.now();

ZonedDateTime

특정 지역의 벽시계 시간 의 렌즈를 통해 동일한 동시 모멘트 를 보려면 시간대 ( )를 적용하여 를 얻습니다 .ZoneIdZonedDateTime

시간대

지정 적절한 시간대 이름 의 형식 continent/region예컨대, America/Montreal, Africa/Casablanca, 또는 Pacific/Auckland. 표준 시간대 가 아니EST 거나 표준화되지 않았으며 고유하지 않은 3-4 문자 약어를 사용하지 마십시오 .IST

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();

오프셋

시간대는 해당 지역의 UTC에서 오프셋 변경 내역입니다 . 그러나 때로는 전체 영역이없는 오프셋 만 제공됩니다. 이 경우 OffsetDateTime클래스를 사용하십시오 .

ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );

단순한 오프셋을 사용하는 것보다 시간대를 사용하는 것이 좋습니다.

LocalDateTime

Local…수업 에서 "지역" 은 특정 지역이 아닌 모든 지역을 의미 합니다 . 따라서 이름은 반 직관적 일 수 있습니다.

LocalDateTime, LocalDateLocalTime오프셋 또는 시간대에 대한 정보가 의도적으로 없습니다. 그들이 그래서 하지 실제 순간을 표현, 그들은 하지 타임 라인에 포인트. 의심이나 혼란에 사용하는 경우 ZonedDateTime보다는 LocalDateTime. 더 많은 논의를 위해 검색 스택 오버플로.

날짜-시간 객체를 해당 값을 나타내는 문자열과 혼동하지 마십시오. 문자열을 구문 분석하여 날짜-시간 객체를 얻을 수 있으며 날짜-시간 객체에서 문자열을 생성 할 수 있습니다. 그러나 문자열은 날짜-시간 자체가 아닙니다.

java.time 클래스에서 기본적으로 사용되는 표준 ISO 8601 형식에 대해 학습 합니다.


java.time에 대하여

java.time의 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이 클래스는 까다로운 기존에 대신 기존 과 같은 날짜 - 시간의 수업을 java.util.Date, Calendar, SimpleDateFormat.

Joda 타임 프로젝트는 지금에 유지 관리 모드 의로 마이그레이션을 조언 java.time의 클래스.

자세한 내용은 Oracle Tutorial을 참조하십시오 . 많은 예제와 설명을 보려면 스택 오버플로를 검색하십시오. 사양은 JSR 310입니다 입니다.

JDBC 4.2 이상 과 호환 되는 JDBC 드라이버를 사용하면 데이터베이스와 직접 java.time 객체를 교환 할 수 있습니다. 문자열이나 java.sql. * 클래스가 필요하지 않습니다.

java.time 클래스는 어디서 구할 수 있습니까?

Java 또는 Android 버전과 함께 사용할 java.time 라이브러리 표

ThreeTen - 추가 프로젝트 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 향후 java.time에 추가 될 수있는 입증 된 근거입니다. 당신은 여기에 몇 가지 유용한 클래스와 같은 찾을 수 있습니다 Interval, YearWeek, YearQuarter, 그리고 .


10

Java 8에서는 새로운 java.time 패키지 사용해야합니다.

개체는 변경할 수 없으며 표준 시간대와 일광 절약 시간이 고려됩니다.

다음 과 같이 ZonedDateTime오래된 java.util.Date객체 에서 객체를 만들 수 있습니다 .

    Date date = new Date();
    ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());

java.time 클래스를 제안하는 것이 좋습니다. 그러나 나쁜 제안 LocalDateTime. 해당 클래스는 UTC에서 오프셋 및 시간대에 대한 정보를 의도적으로 잃습니다. 따라서 클래스는 UTC와 동일 하지 않으며 시간대가 할당되어 있습니다. 다른 답변으로 내 답변 및 멋진 다이어그램 을 참조하십시오. java.util.Date를 "java.time"유형으로 변환? . DateCalendar
Basil Bourque 2012

9

나는 항상 Joda-time을 옹호 합니다 . 이유는 다음과 같습니다.

  1. API는 일관되고 직관적입니다. java.util.Date/Calendar API와 달리
  2. java.text.SimpleDateFormat 과 달리 스레딩 문제로 고통받지 않습니다. 등과 (표준 날짜 / 시간 형식이 스레드로부터 안전하지 않다는 것을 깨닫지 못하는 것과 관련된 많은 클라이언트 문제가 있음을 보았습니다)
  3. 새로운 Java 날짜 / 시간 API ( JSR310 , Java 8 용으로 예약 됨) 의 기초입니다. 따라서 핵심 Java API가 될 API를 사용하게됩니다.

편집 : Java 8로 마이그레이션 할 수 있다면 Java 8과 함께 도입 된 Java 날짜 / 시간 클래스가 선호되는 솔루션입니다.


3
내가 마지막으로 보았을 때, JODA와 JSR-310은 Stephen Colebourne이 작성한 경우에도 매우 다르게 보였습니다. 즉 JODA은 JSR-310도 해결할 수있는 문제가 있음을 날짜 - 시간 문제의 복잡성을 소개 것이라고 말했다
oxbow_lakes

2
질문은 단일 공급 업체 종속성 위험을 프로젝트에 추가하는 타사 라이브러리를 사용하지 않는 Date 및 Calendar 사용에 관한 것이기 때문입니다.
Archimedes Trajano

2
모범 사례는 단순히 해당 클래스를 사용하지 않는 것입니다.
Brian Agnew

3
java.util.Date 및 Calendar 클래스에 대한 알려진 문제점을 감안할 때 Joda-Time (또는 JSR 310)을 제안하는 것이 적절하고 책임이있는 것 같습니다. 우리는 맛이나 미적 스타일의 문제에 대해 이야기하지 않습니다. 누군가 빨간 차를 탈 것인지 실버 차를 탈 것인지 물었고 빨간 차에 타이어가 납작하고은 차에 버스트 라디에이터가 있다는 것을 알았다면 차를 골라야합니까 아니면 택시로 전화해야합니까? Sun / Oracle조차도 그 정크 러를 떠나 새 차를 구매하기로 결정함에 따라 그 질문에 대한 대답은 분명해 보일 것입니다. JSR 310 : Date and Time API.
Basil Bourque

1
참고로 Joda-Time 프로젝트는 이제 유지 관리 모드 에 있으며 java.time 클래스 로의 마이그레이션을 조언합니다 . Oracle의 Tutorial을 참조하십시오 .
Basil Bourque

8

약간 늦었지만 Java에는 JDK 8에 새로운 Date Time API가 있습니다. JDK 버전을 업그레이드하고 표준을 채택 할 수 있습니다. 더 이상 지저분한 날짜 / 달력, 더 이상 타사 항아리가 없습니다.


1

날짜를 다시 개발해야합니다. 긴 interger가 아니라 년, 월, 일,시, 분, 초를 별도의 필드로 보유해야합니다. 이 날짜와 연결된 달력 및 시간대를 저장하는 것이 좋습니다.

자연스러운 대화에서 2013 년 11 월 1 일 오후 1시 (미국 뉴욕시)에 약속을 설정하면 날짜 / 시간입니다. 캘린더가 아닙니다. 따라서 Java에서도 이와 같이 대화 할 수 있어야합니다.

Date가 긴 정수 (1970 년 1 월 1 일 이후 밀리 초 등)로 저장된 경우 현재 날짜 계산은 달력에 따라 다릅니다. 다른 달력은 다른 날짜를 제공합니다. 이는 절대 시간 (예 : 빅뱅 후 1 조 초)을 제공 할 것으로 예상됩니다. 그러나 종종 우리는 연도, 월 등을 캡슐화하는 객체와 같은 편리한 대화 방법이 필요합니다.

이 두 가지 목표를 조정하기 위해 Java에 새로운 발전이 있는지 궁금합니다. 어쩌면 내 자바 지식이 너무 오래되었을 수도 있습니다.


동일한 순간을 동일한 시간에 저장할 수 있지만 다른 달력 시스템에 따라 다른 시간 / 분 / 일 / 주 / 년 / foo를보고한다는 사실은 약점이 아니라 강점입니다. 그것은 (복잡한) 현실을 ​​반영합니다.
ThrawnCA

실제로 Date재개발되었습니다. java.time.Instant수업으로 대체되었습니다 . 그리고 Calendar/ GregorianCalendarjava.time.ZonedDateTime수업 으로 대체되었습니다 .
Basil Bourque

0

Btw "date"는 일반적으로 "폐기 / 더 이상 사용되지 않음"으로 태그됩니다 (정확히 이유를 모르겠습니다) . Java 에 대해 작성된 내용은 다음과 같습니다. Java : Date 생성자가 더 이상 사용되지 않는 이유는 무엇입니까?

새로운 Date (int year, int month, int day) 를 통한 생성자 만의 문제 인 것처럼 보이며 권장되는 방법은 Calendar를 통한 것이고 params를 별도로 설정하는 것입니다 .. ( Calendar cal = Calendar.getInstance (); )


0

시간 이동과 같은 날짜에 특정 작업이 필요할 때 캘린더를 사용하지만 날짜는 필요에 맞게 날짜를 형식화해야 할 때 도움이된다는 것을 알게되었습니다. 지금 로케일을 사용하고 있습니다!


참고로, 귀찮은 CalendarDate클래스에 의해 년 전 대체되었다 java.time의 클래스. 필요가 이제까지 사용하지하는 DateCalendar. 그리고 Locale날짜-시간 객체의 의미와 관련이 없습니다. A Locale는 날짜-시간 객체의 값을 나타내는 텍스트를 생성하는 동안 지역화에 사용될 인간 언어 및 문화적 규범을 지정하는 데만 사용됩니다.
Basil Bourque
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.