Java에서 시간없이 날짜를 얻으려면 어떻게합니까?


235

타임 스탬프없이 현재 날짜를 가져 오기 위해 스택 오버플로 질문 Java 프로그램 에서 계속 :

시간없이 Date 객체를 얻는 가장 효율적인 방법은 무엇입니까? 이 둘 외에 다른 방법이 있습니까?

// Method 1
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dateWithoutTime = sdf.parse(sdf.format(new Date()));

// Method 2
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
dateWithoutTime = cal.getTime();

업데이트 :

  1. 나는 Joda-Time 에 대해 알고 있었다 . 나는 그런 간단한 작업에 대한 추가 라이브러리를 피하려고합니다. 그러나 지금까지의 답변을 바탕으로 Joda-Time은 매우 인기가있는 것으로 보이므로 고려할 수 있습니다.

  2. 에 의해 효율적으로 , 나는 임시 객체 피하려는 의미 String로 사용되는 창조 method 1한편, method 2대신 솔루션의 해킹처럼 보인다.


1
실력 있는? method1에서 제공하는 것보다 더 많은 효율성이 필요하십니까?
Johan Sjöberg

2
"효율적"은 무엇을 의미합니까? 날짜는 기본적으로 긴 형식이므로 실제로는 메모리보다 적은 메모리에서이 작업을 수행 할 수 없습니다. 당신이 "편리한"을 의미한다면, JODA 시간이 갈 길입니다.
millimoose

3
+1 정확히 내가 가진 질문.
Alba Mendez 2016 년

1
나는 메소드 2를 좋아한다. 유틸리티 클래스에서 정적 메소드를 작성하고 사용하면된다. 나는 몇 년 동안이 접근법을 사용했습니다.
Wilson Freitas

1
"업데이트 1"에 대한 힌트 : "그런 간단한 작업"이라면 썬은 그렇게 끔찍하고 비효율적 인 API를 찾지 못했을 것입니다. 전혀 ;-)
Flávio Etrusco

답변:


108

당신은 절대적으로 마십시오 사용 java.util.Date? 나는 것 철저하게 사용하는 것이 좋습니다 Joda 시간 또는 java.time대신 자바 8에서 패키지를. 특히, 날짜 및 달력 은 "일자"와 같은 개념이없는 특정 순간을 항상 나타내지 만 Joda Time 에는 이 유형 ( LocalDate)을 나타내는 유형이 있습니다. 실제로하려는 작업을 나타내는 유형을 사용할 수 있으면 코드가 훨씬 명확 해집니다.

Joda Time을 사용하거나 java.time내장 java.util유형 대신 다른 많은 이유가 있습니다 . 일반적으로 API가 훨씬 좋습니다. java.util.Date예를 들어 데이터베이스 상호 작용을 위해 필요한 경우 언제든지 자신의 코드 경계 에서 a로 /에서 변환 할 수 있습니다 .


75
엔터프라이즈 응용 프로그램에는 항상 다른 라이브러리를 추가 / 사용할 수있는 옵션이 없습니다. Joda Time에 대한 포인터에 감사하지만 표준 Java를 사용하여 날짜 부분을 가져 오는 원래 문제에 대한 답변은 아닙니다. 감사. Chathuranga의 답변을지지합니다.
noogrub

3
@ noogrub : Chathugranga의 답변은 Date객체 를 얻는 방법에 대해 묻는 원래 질문에 대답하지 않습니다.이 답변은 날짜를 문자열로 형식화 합니다. 기본적으로 어떤 날짜에 날짜를 묻는 지에 Date대한 자세한 정보가없는 의미없는 질문은 시간대와 사용중인 캘린더 시스템입니다.
Jon Skeet

7
"엔터프라이즈 응용 프로그램에는 항상 다른 라이브러리를 추가 / 사용할 수있는 옵션이 없습니다". 정말 ? 타사 라이브러리를 전혀 사용할 수 없다는 것을 제안하고 있습니까?
Brian Agnew

3
@BrianAgnew noogrub의 의견이 아닌 기술 제약과 관련이있을 것 같다, 내 생각
Jose_GD

3
오늘의 관점에서 : " Joda-Time 은 Java SE 8 이전의 Java의 사실상 표준 날짜 및 시간 라이브러리입니다. 이제 사용자는 java.time (JSR-310)으로 마이그레이션해야합니다."
Drux

66

다음은 시간을 설정하여 오늘 날짜를 얻는 데 사용한 내용입니다 00:00:00.

DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");

Date today = new Date();

Date todayWithZeroTime = formatter.parse(formatter.format(today));

28
원래 질문에서 이미 제안 된 "방법 1"과 다른 점은 무엇입니까?
Chris

이것이 발생하는 시간대를 다루지 않습니다 (JVM의 임의의 기본 시간대에서 왼쪽으로).
Darrell Teague 18

58

Apache Commons 라이브러리에서 DateUtils.truncate 를 사용할 수 있습니다 .

예:

DateUtils.truncate(new Date(), java.util.Calendar.DAY_OF_MONTH)

3
새 라이브러리를 추가하려면 Apache Commons 대신 Joda로 설정하십시오.
Dibbeke

6
+1 @Dibbeke 차이점은 다른 라이브러리 대신 하나의 라이브러리를 추가한다는 것만이 아닙니다. 때로는 날짜에서 시간을 잘라내는 사소한 작업을 위해 완전히 새로운 라이브러리를 배우고 싶지 않습니다. 또는 날짜 / 달력과 Joda 날짜를 혼합하는 코드를 원하지 않는 경우가 있습니다. 또는 잘 작동하는 모든 날짜 / 달력 기반 코드를 사소한 목적으로 다른 라이브러리로 바꾸는 것을 감당할 수 없습니다. Joda가 분명히 우월하고 단순히 옳은 일이기 때문에 확실히 좋습니다. 때로는 실제 생활이 시작됩니다.
SantiBailors

천재! 나를 도와주었습니다
Thiesen

37

이 둘 외에 다른 방법이 있습니까?

그렇습니다.

LocalDate.now( 
    ZoneId.of( "Pacific/Auckland" ) 
)

java.time

Java 8 이상에는 새로운 java.time 패키지가 내장되어 있습니다. 튜토리얼을 참조하십시오 . 많은 java.time 기능은 자바 6 7 백 포팅 ThreeTen - 백 포트 및 상기 안드로이드 적응 ThreeTenABP .

Joda-Time 과 유사하게 , java.time은 LocalDate시간대와 시간대가없는 날짜 전용 값을 나타내는 클래스를 제공합니다 .

참고 시간대가 중요한 특정 날짜를 결정합니다. 예를 들어 파리 자정이되었을 때 날짜는 여전히 몬트리올에서 "어제"입니다.

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) ) ;

기본적으로 java.time은 날짜 또는 날짜-시간 값의 문자열 표시를 생성 할 때 ISO 8601 표준을 사용합니다 . (Joda-Time과의 또 다른 유사점) 간단히 호출하여과 toString()같은 텍스트를 생성하십시오 2015-05-21.

String output = today.toString() ; 

java.time에 대하여

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

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

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

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

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


1
시간대 를 언급 해 주셔서 감사 합니다 . "어떤 날인지"가 절대적인 개념이 아니라는 것은 나에게 일어나지 않았다.
ToolmakerSteve

@ToolmakerSteve 날짜를 가져 오려면 항상 시간대가 필요합니다. 그러나 요령은 시간대를 지정하지 않으면 JVM의 현재 기본 시간대 가 날짜 결정에 자동으로 적용된다는 것입니다. 또한 JVM의 현재 기본 시간대는 언제든지 변경할 수 있습니다 ! JVM 내 앱의 스레드에있는 모든 코드는 TimeZone.setDefault런타임 중에 호출 할 수 있으며 해당 JVM에서 실행중인 다른 모든 코드에 즉시 영향을줍니다. 이야기의 교훈 : 항상 시간대를 지정하십시오.
Basil Bourque

22

가장 간단한 방법 :

long millisInDay = 60 * 60 * 24 * 1000;
long currentTime = new Date().getTime();
long dateOnly = (currentTime / millisInDay) * millisInDay;
Date clearDate = new Date(dateOnly);

5
나를 위해,이 현재 : "토 2월 19일 01 : 00 : 중부 유럽 표준시 00시 2011". 그것을 사용하려면 UTC 만 사용하십시오.
Chris Lercher

4
3 행 long dateOnly = (currentTime / millisInDay) * millisInDay;은 글쓰기와 같지 long dateOnly = currentTime;않습니까?
Chris

5
정수 수학 때문에 그렇지 않습니다. Math.floor (currentTime / millisInDay) * millisInDay와 같이 생각하십시오. 그는 효과적으로 시간을 00:00:00으로 설정하고 있습니다.
Nicholas Flynt 2016 년

2
이 솔루션은 대부분의 응용 프로그램에 적합 할 수 있지만 하루에 60 * 60 * 24 * 1000이 항상 있다고 가정하지는 않습니다. 예를 들어 며칠 만에 도약 할 수 있습니다.
Pierre-Antoine

1
이것은 아마도 가장 난해하고 다른 1 줄과 2 줄의 명확하고 간결한 방법보다 권장되지 않는 방법입니다.
Darrell Teague

22

이 질문에 대한 표준 답변은 Joda Time 을 사용하는 것 입니다. API가 더 좋으며 포맷터와 파서를 사용하는 경우 직관적이지 않은 스레드 안전성 부족을 피할 수 있습니다 SimpleDateFormat.

Joda를 사용하면 간단히 할 수 있습니다.

LocalDate d = new LocalDate();

업데이트 : : Java 8을 사용하면 이것을 사용하여 달성 할 수 있습니다

LocalDate date = LocalDate.now();

Java 8의 새로운 java.time 패키지는 LocalDateJoda-Time과 유사한 클래스 도 제공합니다 .
Basil Bourque

1
이상적으로는 DateTimeZone해당 LocalDate 생성자에 a 를 전달합니다 . 파리가 몬트리올 이전의 새로운 날짜를 시작하므로 현재 날짜를 결정하는 것은 시간대에 따라 다릅니다. 시간대를 생략하면 JVM의 기본 시간대가 적용됩니다. 일반적으로 기본값을 사용하는 것보다 지정하는 것이 좋습니다.
Basil Bourque

8

이것은 간단한 방법입니다.

Calendar cal = Calendar.getInstance();
SimpleDateFormat dateOnly = new SimpleDateFormat("MM/dd/yyyy");
System.out.println(dateOnly.format(cal.getTime()));

4
이 답변은 질문을 해결하지 못합니다. 형식화 된 문자열을 얻는 것이 목표가 아닙니다.
Basil Bourque

7

표준 java 런타임의 Date 루틴과 관련하여 타임 스탬프가없는 날짜에 대해 이야기하는 것은 의미가 없습니다. 기본적으로 날짜가 아닌 특정 밀리 초로 매핑되기 때문입니다. 상기 밀리 초는 본질적으로 하루 중 시간이 연결되어 일광 절약 시간 및 기타 캘린더 조정과 같은 시간대 문제에 취약하다. 참조 왜 이상한 결과를 제공 (1927 년)이 두 번을 뺀입니까? 흥미로운 예입니다.

밀리 초 대신 날짜를 사용하려면 다른 것을 사용해야합니다. Java 8의 경우 원하는 것을 정확하게 제공하는 새로운 메소드 세트가 있습니다. Java 7 이하의 경우 http://www.joda.org/joda-time/을 사용 하십시오.


3
참고 : "자정 날짜"라는 접근 방식은 일광 절약 시간제와 여러 시간대를 제대로 처리하지 못합니다.
Thorbjørn Ravn Andersen 님이

나는 그것을 확인하고 내 앱에서 하루 씩 날짜를 늘리고 있었고 DST가있는 시간대의 사용자로부터 버그 보고서를 통해 이것에 대해 배웠습니다 (국가는 DST를 사용하지 않습니다). DST가 시작되는 날에 앱이 12 시간 대신 11 시간을 추가합니다. "정오"날짜의 시간으로 정오를 사용하는 것이 더 좋을까요?
Jose_GD

1
@Jose_GD 여전히 해킹 상태입니다. youtube.com/watch?v=-5wpm-gesOY 엔터테인먼트를 찾을 수 있습니다 .
Thorbjørn Ravn Andersen

@ Thorbjorn, 당신은 맞습니다. 단지 하나의 기능 사운드 과잉에 대한 라이브러리를 추가하기 때문에 JodaTime을 피하고 싶었습니다. 나는 그 비디오에 대해 정말로 재미 있었다.
Jose_GD

1
@Jose_GD 요점은 당신의 접근 방식이 버그로 간주되는 실제 실제 사용 사례가 있다는 것입니다. 당신이 하나를 발견하면 더있을 수 있습니다 ... 나는 Joda가 이것을 처리하는 방법을 모르겠지만, 당신은 볼 수 있습니다. 또한 Java 8은 새로운 날짜-시간 라이브러리 (Joda 사용 경험을 기반으로 함)를 제공합니다.
Thorbjørn Ravn Andersen

4

확실히 가장 정확한 방법은 아니지만 시간없이 날짜를 얻는 빠른 솔루션이 필요하고 타사 라이브러리를 사용하지 않으려면이 작업을 수행해야합니다

    Date db = db.substring(0, 10) + db.substring(23,28);

나는 시각적 목적을 위해 날짜 만 필요했고 Joda는 그렇게 할 수 없었으므로 하위 문자열을 만들었습니다.


4
// 09/28/2015
System.out.println(new SimpleDateFormat("MM/dd/yyyy").format(Calendar.getInstance().getTime()));

// Mon Sep 28
System.out.println( new Date().toString().substring(0, 10) );

// 2015-09-28
System.out.println(new java.sql.Date(System.currentTimeMillis()));

// 2015-09-28
// java 8
System.out.println( LocalDate.now(ZoneId.of("Europe/Paris")) ); // rest zones id in ZoneId class

3

글쎄, 내가 아는 한 표준 JDK 만 사용하면 더 쉽게 달성 할 수있는 방법이 없습니다.

물론 toBeginningOfTheDay-method에서 와 같이 method2의 로직을 도우미 클래스의 정적 함수에 넣을 수 있습니다.

그런 다음 두 번째 방법을 단축하여 다음을 수행 할 수 있습니다.

Calendar cal = Calendar.getInstance();
Calendars.toBeginningOfTheDay(cal);
dateWithoutTime = cal.getTime();

또는이 형식으로 현재 날짜가 너무 자주 필요한 경우 다른 정적 도우미 메서드로 마무리하여 하나의 라이너로 만들 수 있습니다.


3

"YYYY-MM-DD"와 같이 다른 모든 혼란없이 날짜를 보려면 "Thu May 21 12:08:18 EDT 2015"만 사용하면 java.sql.Date됩니다. 이 예제는 현재 날짜를 가져옵니다.

new java.sql.Date(System.currentTimeMillis());

또한 java.sql.Date의 서브 클래스입니다 java.util.Date.


3

시간없이 현재 날짜 만 필요한 경우 다른 옵션은 다음과 같습니다.

DateTime.now().withTimeAtStartOfDay()

1
질문은 시간을 요구하지 않았습니다. 결과는 실제로 시간이 실제로있는 날짜-시간 객체입니다 00:00:00( DST 와 같은 예외의 시간대에 따라 다를 수 있음 ). 따라서 다른 답변에서 알 수 있듯이 LocalDateJoda-Time에서 클래스가 더 적합합니다 (Joda-Time을 참조한다고 가정하면 Java와 번들로 제공되지 않은 클래스를 인용 할 때 명시 적으로 지적해야합니다).
Basil Bourque

3

다음 LocalDate.now()Date같이 사용 하고 변환 하십시오 .

Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());

1
JVM의 현재 기본 시간대는 런타임 중에 언제든지 변경할 수 있습니다. JVM 내에서 모든 앱 스레드의 모든 코드는를 호출 할 수 있습니다 TimeZone.setDefault. 코드가 ZoneId.systemDefault두 번 호출 중이고 첫 번째는 암시 적이며 LocalDate.now()두 번째는로 명시 적입니다 atStartOfDay. 런타임시이 두 순간 사이에 현재 기본 영역이 변경 될 수 있습니다. 영역을 변수로 캡처하고 두 가지 방법으로 전달하는 것이 좋습니다.
Basil Bourque

2

반향 목적으로 만 날짜 부분이 필요한 경우

Date d = new Date(); 
String dateWithoutTime = d.toString().substring(0, 10);

1
나는 이것이 i18n 친화적이라고 생각하지 않는다
Mark Lapasa

2

이건 어때?

public static Date formatStrictDate(int year, int month, int dayOfMonth) {
    Calendar calendar = Calendar.getInstance();
    calendar.set(year, month, dayOfMonth, 0, 0, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    return calendar.getTime();
}

1

Veyder-time을 확인하십시오 . java.util과 Joda-time에 대한 간단하고 효율적인 대안입니다. 타임 스탬프없이 날짜 만 나타내는 직관적 인 API 및 클래스가 있습니다.


1

Java의 거대한 TimeZone 데이터베이스를 최대한 활용하고 올바른 가장 획기적인 방법입니다.

long currentTime = new Date().getTime();
long dateOnly = currentTime + TimeZone.getDefault().getOffset(currentTime);

1

다음은 문자열로 변환하지 않고 깨끗한 솔루션이며 시간의 각 구성 요소를 0으로 재설정 할 때 시간을 여러 번 다시 계산하지 않습니다. 또한 사용% 이중 연산을 피하기 위해 나누기 대신 곱하기 대신 (모듈러스)를 합니다.

타사 종속성이 필요하지 않으며 전달 된 Calender 객체의 시간대를 반영합니다.이 함수는 전달한 날짜 (캘린더) 시간대의 오전 12시에 시간을 반환합니다.

public static Calendar date_only(Calendar datetime) {
    final long LENGTH_OF_DAY = 24*60*60*1000;
    long millis = datetime.getTimeInMillis();
    long offset = datetime.getTimeZone().getOffset(millis);
    millis = millis - ((millis + offset) % LENGTH_OF_DAY);
    datetime.setTimeInMillis(millis);
    return datetime;
}

DST (Summer Tme)를 존중할 것이라고 확신하지 못합니까?
Ole VV

0

타사 라이브러리를 최대한 사용하지 않는 것이 좋습니다. 나는이 방법이 전에 언급되었다는 것을 알고 있지만 여기에 좋은 깨끗한 방법이 있습니다.

  /*
    Return values:
    -1:    Date1 < Date2
     0:    Date1 == Date2
     1:    Date1 > Date2

    -2:    Error
*/
public int compareDates(Date date1, Date date2)
{
    SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");

    try
    {
        date1 = sdf.parse(sdf.format(date1));
        date2 = sdf.parse(sdf.format(date2));
    }
    catch (ParseException e) {
        e.printStackTrace();
        return -2;
    }

    Calendar cal1 = new GregorianCalendar();
    Calendar cal2 = new GregorianCalendar();

    cal1.setTime(date1);
    cal2.setTime(date2);

    if(cal1.equals(cal2))
    {
        return 0;
    }
    else if(cal1.after(cal2))
    {
        return 1;
    }
    else if(cal1.before(cal2))
    {
        return -1;
    }

    return -2;
}

음, GregorianCalendar를 사용하지 않는 것이 옵션 일 수 있습니다!


0

방금 내 앱 에서이 작업을 수행했습니다.

public static Date getDatePart(Date dateTime) {
    TimeZone tz = TimeZone.getDefault();
    long rawOffset=tz.getRawOffset();
    long dst=(tz.inDaylightTime(dateTime)?tz.getDSTSavings():0);
    long dt=dateTime.getTime()+rawOffset+dst; // add offseet and dst to dateTime
    long modDt=dt % (60*60*24*1000) ;

    return new Date( dt
                    - modDt // substract the rest of the division by a day in milliseconds
                    - rawOffset // substract the time offset (Paris = GMT +1h for example)
                    - dst // If dayLight, substract hours (Paris = +1h in dayLight)
    );
}

Android API 레벨 1, 외부 라이브러리 없음 일광 및 기본 시간대를 따릅니다. 문자열 조작이 없으므로이 방법이 CPU보다 효율적이라고 생각하지만 테스트를하지 않았습니다.


0

요다 시간을 사용할 수 있습니다.

private Date dateWitoutTime(Date date){
 return new LocalDate(date).toDate()
}

그리고 당신은 전화 :

Date date = new Date();
System.out.println("Without Time = " + dateWitoutTime(date) + "/n  With time = " + date);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.