Javaで時間なしの日付を取得するにはどうすればよいですか?


235

Stack Overflowの質問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は非常に人気があるように思われるので、それを検討するかもしれません。

  2. することにより、効率的な、私は一時的なオブジェクト避けたいわけStringで使用されるように作成しmethod 1、一方method 2の代わり液のハックのように思えます。


1
効率的ですか?たとえばmethod1によって提供されるものよりも効率が必要ですか?
JohanSjöberg、2011

2
「効率的」とはどういう意味ですか?日付は基本的に長い型であり、それより少ないメモリでこれを行うことはできません。「便利」という意味なら、JODAの時間が最適です。
ミリムース

3
+1 まさに私が持っていた質問。
アルバメンデス

1
私はメソッド2が好きです。ユーティリティクラスで静的メソッドを作成し、それを使用します。私はこのアプローチを何年も続けてきました。
Wilson Freitas

1
あなたの「アップデート1」を手に取る:それが「そのような単純なタスク」だったとしたら、Sunはそのような恐ろしく非効率的なAPIにたどり着かなかったと思います。まったく;-)
フラビオエトルスコ2013

回答:


108

絶対に使用する必要がありますjava.util.Dateか?代わりにJoda TimeまたはJava 8のパッケージを使用することを徹底的にお勧めします。特に、日付とカレンダーは常に特定の瞬間を表しますが、「単なる日付」などの概念ありませんが、Joda Time これを表すタイプを持ってます()。実際に実行しようとしていることを表す型を使用できれば、コードはより明確になります。java.timeLocalDate

Joda Timeを使用したりjava.time、組み込みのjava.utilタイプの代わりに使用する理由は他にもたくさんあります。これらは一般にはるかに優れたAPIです。java.util.Dateたとえばデータベースとのやり取りが必要な場合は、独自のコードの境界でaとの間でいつでも変換できます。


75
エンタープライズアプリケーションでは、他のライブラリを追加/使用するオプションが常にあるとは限りません。私はJoda Timeへのポインターに感謝しますが、標準のJavaを使用して日付部分を取得するという元の問題への回答ではありません。ありがとう。チャトゥランガの答えを支持する。
noogrub 2013

3
@noogrub:Chathugrangaの答えは、Dateオブジェクトを取得する方法について尋ねている元の質問に答えません-その答えは日付を文字列にフォーマットしますが、これは同じではありません。基本的に、a Dateが何日であるかを尋ねるのは意味のない質問です。これは、使用しているタイムゾーンとカレンダーシステムの詳細情報がなければ意味がありません。
Jon Skeet 2013

7
「エンタープライズアプリケーションでは、他のライブラリを追加/使用するオプションが常にあるとは限りません。」本当に ?サードパーティのライブラリをまったく使用できないことを示唆していますか?
Brian Agnew 2014年

3
@BrianAgnew noogrubのコメントは、技術以外の制約に関連しているようです
Jose_GD

3
今日の観点から:「Joda-Timeは、Java SE 8より前のJavaの事実上の標準の日付と時刻のライブラリです。ユーザーはjava.time(JSR-310)に移行するように求められます。」
Drux、2016

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の任意のデフォルトタイムゾーンに任せます)。
ダレルティーグ

58

Apache CommonsライブラリのDateUtils.truncateを使用できます。

例:

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

3
新しいライブラリを追加する場合は、Apache CommonsではなくJodaを使用してください。
Dibbeke

6
+1 @Dibbeke違いは、あるライブラリを別のライブラリではなく追加することだけではありません。時々、日付から時間を切り捨てるというささいなタスクのために、まったく新しいライブラリを学びたくない場合があります。あるいは、日付/カレンダーをJodaの日付と前者と後者を使用するコードと混在させたくありません。または、そのような些細な目的のために、正常に機能するすべての日付/カレンダーベースのコードを別のライブラリに置き換える余裕がない/正当化できない。それは時々 、現実のキックだけで正しく明らかに優れているとして示唆ジョダはで確かに良いですが。
SantiBailors

天才!たくさん助けてくれました
ティーセン

37

この二つ以外に方法はありますか?

はいあります。

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

java.time

Java 8以降には、新しいjava.timeパッケージが組み込まれています。チュートリアルを参照してください。java.time機能の多くは、ThreeTen -BackportでJava 6および7にバックポートされ、さらにThreeTenABPで Androidに適合しています

Joda -Timeと同様に、java.timeは、LocalDate時刻とタイムゾーンなしで日付のみの値を表すクラスを提供します。

ことに注意してくださいタイムゾーンが重要である特定の日付を決定します。たとえば、パリの真夜中、日付はまだモントリオールの「昨日」のままです。

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

デフォルトでは、java.timeはISO 8601標準を使用して、日付または日時値の文字列表現を生成します。(Joda-Timeとのもう1つの類似点。)したがって、を呼び出すだけで、のtoString()ようなテキストを生成できます2015-05-21

String output = today.toString() ; 

java.timeについて

java.timeのフレームワークは、Java 8に組み込まれており、後にされています。これらのクラスは面倒古い取って代わるレガシーのような日付時刻クラスをjava.util.DateCalendar、& SimpleDateFormat

ジョダタイムプロジェクトは、今でメンテナンスモードへの移行をアドバイスjava.timeのクラス。

詳細については、Oracleチュートリアルを参照してください。また、スタックオーバーフローで多くの例と説明を検索してください。仕様はJSR 310です。

java.timeクラスはどこで入手できますか?

  • Java SE 8 Java SE 9以降
    • 内蔵。
    • 実装がバンドルされた標準Java APIの一部。
    • Java 9には、いくつかのマイナーな機能と修正が追加されています。
  • Java SE 6および Java SE 7
    • java.time機能の多くはThreeTen-BackportでJava 6&7にバックポートされています。
  • アンドロイド
    • Androidの新しいバージョンには、java.timeクラスの実装がバンドルされています。
    • 以前のAndroidでは、ThreeTenABPプロジェクトはThreeTen-Backport(上記)を採用しています。ThreeTenABPの使用方法…を参照してください。

ThreeTen-エクストラプロジェクトでは、追加のクラスでjava.timeを拡張します。このプロジェクトは、java.timeに将来追加される可能性があることを証明する場です。あなたはここにいくつかの有用なクラスのような見つけることがIntervalYearWeekYearQuarter、および多くを


1
タイムゾーンについて言及いただきありがとうございます。「何日か」が絶対的なコンセプトではないということは思いもよらなかった。
ToolmakerSteve、2015

@ToolmakerSteve日付の取得には常にタイムゾーンが含まれます。しかし、トリックは、タイムゾーンの指定に失敗した場合、JVMの現在のデフォルトのタイムゾーンが日付の決定に自動的に適用されることです。その上、JVMの現在のデフォルトのタイムゾーンはいつでも変更できます。JVM内の任意のアプリの任意のスレッドの任意のコードは、TimeZone.setDefault実行時に呼び出すことができ、そのJVMで実行されている他のすべてのコードにすぐに影響します。ストーリーのモラル:常にタイムゾーンを指定します。
バジルブルク

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 CET 2011"。それを使用したい場合は、UTCでのみ使用してください。
Chris Lercher、2011

4
3行目long dateOnly = (currentTime / millisInDay) * millisInDay;は書くのと同じではありませんlong dateOnly = currentTime;か?
Chris

5
整数演算のため、そうではありません。Math.floor(currentTime / millisInDay)* millisInDayのように考えてください。彼は事実上、時間を00:00:00に設定しています。
ニコラスフリント2013年

2
このソリューションはほとんどのアプリケーションでおそらく問題ありませんが、1日が60 * 60 * 24 * 1000であるとの仮定は常に正しいとは限らないことに注意してください。たとえば、ある日にはうるう秒を持つことができます。
Pierre-Antoine

1
これは間違いなく最も鈍く、他の1および2行の明確で簡潔な方法よりも推奨されない方法です。
ダレルティーグ

22

これらの質問に対する標準的な答えは、Joda Timeを使用することです。APIの方が優れており、フォーマッターとパーサーを使用している場合は、スレッドセーフの直感的でない欠如を回避できますSimpleDateFormat

Jodaを使用すると、次のことが簡単に行えます。

LocalDate d = new LocalDate();

更新:: Java 8を使用すると、これを使用してこれを達成できます

LocalDate date = LocalDate.now();

Java 8の新しいjava.timeパッケージも、Joda LocalDate-Timeと同様のクラスを提供します。
バジルブルク2014年

1
理想的には、DateTimeZoneそのLocalDateコンストラクタにを渡します。パリはモントリオールよりも早く新しい日付を開始するため、現在の日付の決定はタイムゾーンによって異なります。タイムゾーンを省略すると、JVMのデフォルトのタイムゾーンが適用されます。通常は、デフォルトに依存するよりも指定することをお勧めします。
バジルブルク2014年

8

これは簡単な方法です:

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

4
この答えは質問に対処できません。フォーマットされた文字列を取得することは目的ではありませんでした。
バジルブルク2014

7

標準のJavaランタイムのDateルーチンに関しては、基本的に日付ではなく特定のミリ秒にマップされるため、タイムスタンプなしの日付について話すことは意味がありません。このミリ秒には、本質的に時刻が付加されているため、夏時間やその他のカレンダー調整などのタイムゾーンの問題に対して脆弱になります。なぜこれらの2回の減算(1927年)が奇妙な結果をもたらすのかを参照してください興味深い例については。

ミリ秒の代わりに日付を操作したい場合は、別のものを使用する必要があります。Java 8の場合、要求したとおりに提供する一連の新しいメソッドがあります。Java 7以前の場合は、http://www.joda.org/joda-time/を使用します


3
注:「真夜中の日付」と言うアプローチは、夏時間と複数のタイムゾーンをうまく処理しません。
–ThorbjørnRavn Andersen、2011

私はそれを確認しました。アプリで日付を1日増やしており、夏時間のあるタイムゾーンのユーザーからのバグレポートでこのことを学びました(私の国では夏時間を使用していません)。DSTが開始する日、私のアプリは12ではなく11時間を追加します。おそらく、「時間がない」日付の時間として正午を使用する方が良いでしょうか?
Jose_GD

1
@Jose_GDそれはせいぜいまだハックです。youtube.com/watch?v=-5wpm-gesOYが面白いかもしれません。
するThorbjörnRavnアンデルセン

@ソービョルン、そうだね、JodaTimeを避けたかったのは、機能追加用のライブラリを1つだけ追加したからだ。私はそのビデオを知っていた、確かに面白い。
Jose_GD 2014

1
@Jose_GDポイントは、アプローチがバグと見なされる実際の実際のユースケースがあるということでした。見つけた場合、もっとあるかもしれません...私はJodaがこれをどのように処理するかわかりませんが、あなたは見ることができます。また、Java 8には、(Jodaでの経験に基づいた)新しい日時ライブラリが含まれているので、これを調べてみてください。
–ThorbjørnRavn Andersen 2014

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メソッドで行っように、method2のロジックをヘルパークラスの静的関数に入れることができます。

次に、2番目の方法を以下のように短縮できます。

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

または、この形式で今日の日が本当に頻繁に必要な場合は、別の静的ヘルパーメソッドでラップして、1行にすることができます。


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などの異常のタイムゾーンによって異なる場合があります)です。したがって、他のアンサーが注記しているように、LocalDateクラスはJoda-Timeからの方が適切です(Javaにバンドルされていないクラスを引用するときに明示的に注意する必要があるJoda-Timeを参照している場合)。
バジルブルク

3

以下のように使用LocalDate.now()して変換しDateます。

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

1
JVMの現在のデフォルトのタイムゾーンは、実行中いつでも変更できます。JVM内の任意のアプリの任意のスレッド内の任意のコードがを呼び出すことができますTimeZone.setDefault。コードがZoneId.systemDefault2回呼び出され、最初のコードは暗黙的でLocalDate.now()、2番目はで明示的atStartOfDayです。実行時のこれら2つの瞬間の間に、現在のデフォルトゾーンが変更される可能性があります。ゾーンを変数にキャプチャし、両方のメソッドに渡すことをお勧めします。
バジルブルク2018

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

これは、文字列への変換とその逆変換がないクリーンなソリューションです。また、時間の各コンポーネントをゼロにリセットしても、時間を数回再計算しません。それも使用します%、除算の後に乗算を行うのではなく、(係数)をして、二重演算を回避します。

サードパーティの依存関係は必要なく、渡されたカレンダーオブジェクトのタイムゾーンを尊重します。この関数は、渡された日付(カレンダー)のタイムゾーンの午前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)を尊重すると確信していませんか?
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、外部ライブラリなし。日光とデフォルトのtimeZoneを尊重します。文字列操作がないので、この方法はあなたよりも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.