Java : Date 생성자가 더 이상 사용되지 않는 이유는 무엇입니까?


212

나는 C # 세계에서 왔으므로 아직 Java에 익숙하지 않습니다. 나는 Date더 이상 사용되지 않는 Eclipse에 의해 들었다 .

Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));

왜? 그리고 대신 (특히 위와 같은 경우) 무엇을 사용해야합니까?


37
비슷한 학습 곡선을 경험하고 있으며 C #에서 Java로 이동합니다. 나를 괴롭히는 또 다른 것은 달이 0 기반 시스템 (1 월 = 0 및 12 월 = 11 인 0 ~ 11)이지만 해당 월의 일은 1 기반 (1 ~ 31)이라는 것입니다. 저것에 향한다!
Paul Sasik

2
@Paul Sasik, 그렇습니다. 그러나 Calendar.JANUARY 상수가 있으며, 매월 1 개가 있습니다
Diogo

5
@PaulSasik lol. 그래, 멍청한 자바 C #에서 Java 및 OMG로 전환해야했던 고통과 불행.
cbmeeks


8
.Net이 훌륭한 Java 라이브러리 Joda-Time 포트에서 적절한 날짜 시간 라이브러리 ( Noda Time )를 얻었 기 때문에 C # 사람들의 Java에 대한 기발한 "lol"발표가 나를 웃게했습니다 .
Basil Bourque

답변:


98

특정 Date생성자는 더 이상 사용되지 않으므로 Calendar대신 사용해야합니다. JavaDoc에 대한 날짜 생성자가 사용되지되는과를 사용하여 교체하는 방법에 대해 설명합니다 Calendar.


25
캘린더에는 추가 객체가 필요하며 8 줄 더 많은 코드가 동일한 작업을 수행하기 위해 내가 말할 수있는 날짜 객체를 만드는 것입니다. 시간대 조정 변수가 아닌 날짜 만 필요할 때 혼란스럽고 불필요하게 보입니다.
G_V

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

250

java.util.Date클래스는 실제로 다른 생성자 / 메소드가되지 않습니다 몇과 함께 그냥 생성자, 사용되지되지 않습니다. 국제화에서는 이러한 종류의 사용법이 제대로 작동하지 않기 때문에 사용되지 않습니다. Calendar클래스는 대신 사용해야합니다 :

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1988);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
Date dateRepresentation = cal.getTime();

Javadoc 날짜를 살펴보십시오.

http://download.oracle.com/javase/6/docs/api/java/util/Date.html


2
이것이 가장 좋은 대답이어야합니다. 감사.
jordaniac89

"국제화와 잘 작동하지 않습니다"라고 말하면 Date에 TimeZone을 할당 할 수 없습니까? 감사합니다
DiveInto

어떤 날짜가 문자열을 구문 분석 했습니까? 그 대신 이제 년, 월 및 일을 포함하는 문자열을 하위 문자열로 만들어야합니까? 대부분의 경우 복잡한 논리와 메소드를 추가 할 필요가없는 무언가에 대한 추가 번거 로움처럼 보입니다.
G_V

1
추가하기 위해 기본 시간대가 고려됩니다. 다른 시간대를 지정하려면Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(<timezone id>));
Vikas Prasad

1
"Calendar 클래스를 대신 사용해야합니다." -Java 8 이상의 java.time.*경우 코드를 변경하는 경우 클래스가 더 나은 옵션입니다.
Stephen C

73

tl; dr

LocalDate.of( 1985 , 1 , 1 )

…또는…

LocalDate.of( 1985 , Month.JANUARY , 1 )

세부

java.util.Date, java.util.Calendar그리고 java.text.SimpleDateFormat자바가 처음 출시 진화 할 때 클래스는 너무 빨리 돌진했다. 수업은 잘 설계되거나 구현되지 않았습니다. 개선이 시도되었으므로 더 이상 사용되지 않습니다. 불행히도 개선 시도는 크게 실패했습니다. 당신은해야 이러한 클래스를 피하기 전부. 그것들은 새로운 클래스에 의해 Java 8에서 대체됩니다.

코드 문제

java.util.Date에는 날짜와 시간 부분이 있습니다. 코드에서 시간 부분을 무시했습니다. 따라서 Date 클래스는 JVM의 기본 시간대에 정의 된대로 하루의 시작 시간을 가져 와서 해당 시간을 Date 객체에 적용합니다. 따라서 코드 결과는 실행되는 시스템 또는 시간대에 따라 다릅니다. 아마 당신이 원하는 것이 아닙니다.

생년월일과 같이 시간 부분이없는 날짜 만 원하는 경우 Date개체 를 사용하지 않을 수 있습니다 . ISO 8601 형식의 날짜 문자열 만 저장할 수 있습니다 YYYY-MM-DD. 또는 LocalDateJoda-Time 의 객체를 사용 하십시오 (아래 참조).

조다 타임

Java에서 가장 먼저 배울 사항 : Java와 함께 번들로 제공되는 악명 높은 java.util.Date & java.util.Calendar 클래스는 피하십시오 .

로 올바르게에서 언급 user3277382으로 대답 , 사용 중 Joda 타임 또는 새로운 java.time. * 패키지 자바 8.

Joda-Time 2.3의 예제 코드

DateTimeZone timeZoneNorway = DateTimeZone.forID( "Europe/Oslo" );
DateTime birthDateTime_InNorway = new DateTime( 1985, 1, 1, 3, 2, 1, timeZoneNorway );

DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );
DateTime birthDateTime_InNewYork = birthDateTime_InNorway.toDateTime( timeZoneNewYork ); 

DateTime birthDateTime_UtcGmt = birthDateTime_InNorway.toDateTime( DateTimeZone.UTC );

LocalDate birthDate = new LocalDate( 1985, 1, 1 );

콘솔로 덤프…

System.out.println( "birthDateTime_InNorway: " + birthDateTime_InNorway );
System.out.println( "birthDateTime_InNewYork: " + birthDateTime_InNewYork );
System.out.println( "birthDateTime_UtcGmt: " + birthDateTime_UtcGmt );
System.out.println( "birthDate: " + birthDate );

달릴 때…

birthDateTime_InNorway: 1985-01-01T03:02:01.000+01:00
birthDateTime_InNewYork: 1984-12-31T21:02:01.000-05:00
birthDateTime_UtcGmt: 1985-01-01T02:02:01.000Z
birthDate: 1985-01-01

java.time

이 경우 java.time 의 코드 는 Joda-Time 의 코드와 거의 동일합니다 .

시간대 ( ZoneId)를 가져 와서 해당 시간대 ( )에 지정된 날짜-시간 객체를 생성합니다 ZonedDateTime. 그런 다음 Immutable Objects 패턴을 사용하여 이전 객체의 동일한 순간 ( epoch 이후 나노초 수 )을 기반으로하지만 다른 시간대가 지정된 새로운 날짜-시간을 만듭니다 . 마지막으로 LocalDate날짜 나 시간대가없는 날짜를 얻지 만 해당 날짜를 결정할 때 시간대가 적용됩니다 (예 : 새로운 날짜는 오슬로 에서 뉴욕 보다 새벽에 더 일찍 나타납니다 ).

ZoneId zoneId_Norway = ZoneId.of( "Europe/Oslo" );
ZonedDateTime zdt_Norway = ZonedDateTime.of( 1985 , 1 , 1 , 3 , 2 , 1 , 0 , zoneId_Norway );

ZoneId zoneId_NewYork = ZonedId.of( "America/New_York" );
ZonedDateTime zdt_NewYork = zdt_Norway.withZoneSameInstant( zoneId_NewYork );

ZonedDateTime zdt_Utc = zdt_Norway.withZoneSameInstant( ZoneOffset.UTC );  // Or, next line is similar.
Instant instant = zdt_Norway.toInstant();  // Instant is always in UTC.

LocalDate localDate_Norway = zdt_Norway.toLocalDate();

java.time에 대하여

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

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

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

java.time 객체를 데이터베이스와 직접 교환 할 수 있습니다 . JDBC 4.2 이상을 준수 하는 JDBC 드라이버를 사용하십시오 . 문자열이 필요없고 수업이 필요 없습니다 .java.sql.*

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

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


5
근본 원인을 실제로 언급하고 사용 가능한 모든 대안의 적용 범위를 제공하기위한 소품.
mabi

정답이며 Calendar 클래스는 피해야합니다. ThreeTen은 최고의 옵션입니다
ant2009

11

생성자가 더 이상 사용되지 않는 한 가지 이유는 year 매개 변수의 의미가 예상과 다르기 때문입니다. 자바 독은 말한다 :

JDK 버전 1.1 현재로 대체되었습니다 Calendar.set(year + 1900, month, date).

연도 필드는 이후의 연도 수 1900이므로 샘플 코드는 예상대로 작동하지 않을 수 있습니다. 그리고 그게 요점입니다.

일반적으로 DateAPI는 최신 서부 달력 만 지원하며, 고유하게 지정된 구성 요소를 가지고 있으며, 필드를 설정하면 일관성이 없습니다.

CalendarGregorianCalendarAPI는 더 나은보다 Date, 및 제 3 자 Joda 시간 API는 일반적으로 최선을 것으로 생각되었다. Java 8에서는 java.time패키지 를 도입했으며 이제 권장되는 대안입니다.


이 솔루션은 새로운 날짜 (년, 월, 일)와 같이 시간 분-초-밀리 초 동안 0 시간을 사용하지 않는다는 점을 제외하고는 효과적입니다. 따라서 다음과 같은 것이 필요합니다. Calendar cal = Calendar.getInstance (); cal.clear (); cal.set (연도 + 1900, 월, 일); 날짜 dateRepresentation = cal.getTime ();
Joel Richard Koett 19

11

나는이 질문을 새로운 질문 의 사본으로 보았습니다.이 질문Date 은 특정 년, 월, 일에 비추천 방법이 무엇인지 묻습니다 .

지금까지의 대답은 Calendar클래스 를 사용한다고 말하고 Java 8이 나올 때까지는 사실이었습니다. 그러나 Java 8 에서이 작업을 수행하는 표준 방법은 다음과 같습니다.

LocalDate localDate = LocalDate.of(1985, 1, 1);

그리고 정말로 당신이 정말로 필요하다면 java.util.Date, 당신은 이 질문에 있는 제안들을 사용할 수 있습니다 .

자세한 정보 는 API 또는 Java 8 용 학습서 를 확인하십시오 .


7

제발 참고 Calendar.getTime()의미에서 비 결정적인 그 일 시간 현재 시간 부분으로 기본 설정됩니다.

재현하려면 다음 코드를 두 번 실행하십시오.

Calendar c = Calendar.getInstance();
c.set(2010, 2, 7); // NB: 2 means March, not February!
System.err.println(c.getTime());

출력 예 :

Sun Mar 07 10:46:21 CET 2010

몇 분 후에 정확히 동일한 코드를 실행하면 다음과 같은 결과가 나타납니다.

Sun Mar 07 10:57:51 CET 2010

따라서 set()해당 필드를 강제로 값을 수정하지만 다른 필드의 시스템 시간이 누출됩니다. (Sun jdk6 및 jdk7로 위에서 테스트 됨)




2

Date 생성자가 더 이상 사용되지 않으므로이 코드를 사용해 볼 수 있습니다.

import java.util.Calendar;

  Calendar calendar = Calendar.getInstance();
     calendar.set(Calendar.HOUR_OF_DAY, 6);// for 6 hour
     calendar.set(Calendar.MINUTE, 0);// for 0 min
     calendar.set(Calendar.SECOND, 0);// for 0 sec
     calendar.set(1996,0,26);// for Date [year,month(0 to 11), date]

    Date date = new Date(calendar.getTimeInMillis());// calendar gives long value

    String mConvertedDate = date.toString();// Fri Jan 26 06:00:00 GMT+05:30 1996

1
이 끔찍한 클래스는로되어 대체 년 전 가진, 지금은 기존 있습니다 java.time의 JSR 310 제안하기에 정의 된 클래스 DateCalendar2019에서 것은 좋지 조언이다.
Basil Bourque

@BasilBourque 제안에 감사드립니다. 곧 업데이트를 기대하고 있습니다.
Divyanshu Kumar


1

클래스 new Date(year,month,date)를 사용하여 코드에서 와 마찬가지로 메소드를 작성할 수 있습니다 Calendar.

private Date getDate(int year,int month,int date){
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.MONTH, month-1);
    cal.set(Calendar.DAY_OF_MONTH, day);
    return cal.getTime();
}

사용되지 않는 생성자처럼 작동합니다. Date


1
이 몹시 귀찮은 클래스는 현대에 의해 년 전 대체되었다 java.time의 구체적 클래스 InstantZonedDateTime.
Basil Bourque

위의 솔루션은 연도에 1900을 더하고 월에서 1을 빼지 않아야하며 Calendar.getInstance () 행 다음에 cal.clear ()를 실행하여시 / 분 / 초 / 밀리 초가 0이되도록합니다. 날짜 생성자에서 수행).
Joel Richard Koett

1

Date 생성자는 1900 년 이후의 연도 형식 (0부터 시작하는 달, 1부터 시작하는 날짜)으로 시간을 예상하며시 / 분 / 초 / 밀리 초를 0으로 설정합니다.

Date result = new Date(year, month, day);

더 이상 사용되지 않는 Date 생성자에 대해 달력 교체 (0 년, 0 개월, 1 일)를 사용하려면 다음과 같은 것이 필요합니다.

Calendar calendar = Calendar.getInstance();
calendar.clear(); // Sets hours/minutes/seconds/milliseconds to zero
calendar.set(year + 1900, month, day);
Date result = calendar.getTime();

또는 Java 1.8 (0부터 시작하여 1부터 시작하여 월과 일이 있음)을 사용합니다.

Date result = Date.from(LocalDate.of(year + 1900, month + 1, day).atStartOfDay(ZoneId.systemDefault()).toInstant());

다음은 Date, Calendar 및 Java 1.8과 동일한 버전입니다.

int year = 1985; // 1985
int month = 1; // January
int day = 1; // 1st

// Original, 1900-based year, zero-based month, one-based day
Date date1 = new Date(year - 1900, month - 1, day);

// Calendar, zero-based year, zero-based month, one-based day
Calendar calendar = Calendar.getInstance();
calendar.clear(); // Sets hours/minutes/seconds/milliseconds to zero
calendar.set(year, month - 1, day);
Date date2 = calendar.getTime();

// Java-time back to Date, zero-based year, one-based month, one-based day
Date date3 = Date.from(LocalDate.of(year, month, day).atStartOfDay(ZoneId.systemDefault()).toInstant());

SimpleDateFormat format = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss.SSS");

// All 3 print "1985-Jan-01 00:00:00.000"
System.out.println(format.format(date1));
System.out.println(format.format(date2));
System.out.println(format.format(date3));

1
이 끔찍한 클래스 모두에 의해 년 전 대체되었다 java.time의 JSR 310에 정의 된 클래스
바질 우르 큐

날짜, 달력 및 Java 1.8 버전을 표시하도록 답변이 업데이트되었습니다.
Joel Richard Koett

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.