日付と時刻の情報を含むJava Dateオブジェクトがあります。時間情報を切り捨て、時間-分-秒を切り捨てるメソッドを記述したいので、日付だけが残っています。
入力例:
2008-01-01 13:15:00
期待される出力:
2008-01-01 00:00:00
ヒントはありますか?私はこのようなことをしようとしました:
(timestamp / (24 * 60 * 60 * 1000)) * (24 * 60 * 60 * 1000)
しかし、タイムゾーンに問題が発生しました。
recommended日付/時刻操作を行う方法は、 Calendar
オブジェクトを使用することです:
Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(dateObject);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long time = cal.getTimeInMillis();
Apache Commons Langの DateUtils truncateメソッドを見ましたか?
Date truncatedDate = DateUtils.truncate(new Date(), Calendar.DATE);
time要素を削除します。
Joda を見ましたか?これはmuchより簡単で直感的な日付と時刻の操作方法です。たとえば、(たとえば) LocalDateTime と LocalDate オブジェクトの間で簡単に変換できます。
例えば(APIを説明するため)
LocalDate date = new LocalDateTime(milliseconds).toLocalDate()
さらに、日付/時刻フォーマッタに関するいくつかのスレッド安全性の問題を解決し、Javaで日付/時刻の問題を処理するために強く推奨されます。
Java.time クラスがJava 8以降に組み込まれたことを考慮した簡単な更新。
LocalDateTime
には truncatedTo
があり、ここで話していることを効果的に解決します:
LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES)
これは、現在の時間を分単位でのみ表します。
2015-03-05T11:47
DAYSより小さい ChronoUnit
(または TemporalUnit
)を使用して切り捨てを実行できます(切り捨てはLocalDateTimeの時刻部分にのみ適用され、日付部分には適用されないため) )。
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
date = cal.getTime();
Jodaを使用すると、簡単に予定日を取得できます。
バージョン2.7の時点(おそらく2.2よりも前のバージョン以降)で、コメンターが指摘しているように、toDateMidnight
は推奨されないか、適切な名前のwithTimeAtStartOfDay()
が推奨されており、
DateTime.now().withTimeAtStartOfDay()
可能。
より良いAPIの利点が追加されました。
古いバージョンでは、次のことができます
new DateTime(new Date()).toDateMidnight().toDate()
タイムスタンプの場合:
timestamp -= timestamp % (24 * 60 * 60 * 1000)
新しいJava8 APIで切り捨てを行いました。私は1つの奇妙なことに直面しましたが、一般的には切り捨てられます...
Instant instant = date.toInstant();
instant = instant.truncatedTo(ChronoUnit.DAYS);
date = Date.from(instant);
次のように、truncateを使用してApacheのDateUtilsを使用します。
DateUtils.truncate(Calendar.getInstance().getTime(), Calendar.DATE);
Java.util.Date JavaDocsから:
クラスDateは、特定の瞬間をミリ秒の精度で表します
およびJava.sql.Date JavaDocsから:
SQL DATEの定義に準拠するには、Java.sql.Dateインスタンスによってラップされたミリ秒値を、インスタンスが関連付けられている特定のタイムゾーンで時間、分、秒、ミリ秒をゼロに設定して「正規化」する必要があります。
したがって、時間の部分が必要ない場合は、Java.sql.Dateを使用するのが最善のアプローチです
Java.util.Date utilDate = new Java.util.Date();
Java.sql.Date sqlDate = new Java.sql.Date(System.currentTimeMillis());
出力は次のとおりです。
Java.util.Date : Thu Apr 26 16:22:53 PST 2012
Java.sql.Date : 2012-04-26
LocalDateTime.parse( // Lacking an offset or time zone, parse as a `LocalDateTime`. *Not* a specific moment in time.
"2008-01-01 13:15:00".replace( " " , "T" ) // Alter input string to comply with ISO 8601 standard format.
)
.toLocalDate() // Extract a date-only value.
.atStartOfDay( // Do not assume the day starts at 00:00:00. Let class determine start-of-day.
ZoneId.of( "Europe/Paris" ) // Determining a specific start-of-day requires a time zone.
) // Result is a `ZonedDateTime` object. At this point we have a specific moment in time, a point on the timeline.
.toString() // Generate a String in standard ISO 8601 format, wisely extended to append the name of the time zone in square brackets.
2008-01-01T00:00 + 01:00 [ヨーロッパ/パリ]
目的の形式で文字列を生成するには、 DateTimeFormatter
を渡します。
LocalDateTime.parse( // Lacking an offset or time zone, parse as a `LocalDateTime`. *Not* a specific moment in time.
"2008-01-01 13:15:00".replace( " " , "T" ) // Alter input string to comply with ISO 8601 standard format.
)
.toLocalDate() // Extract a date-only value.
.atStartOfDay( // Do not assume the day starts at 00:00:00. Let class determine start-of-day.
ZoneId.of( "Europe/Paris" ) // Determining a specific start-of-day requires a time zone.
) // Result is a `ZonedDateTime` object. At this point we have a specific moment in time, a point on the timeline.
.format( // Generate a String representing the object’s value.
DateTimeFormatter.ISO_LOCAL_DATE_TIME // Built-in predefined formatter close to what you want.
)
.replace( "T" , " " ) // Replace the standard’s use of a 'T' in the middle with your desired SPACE character.
2008-01-01 00:00:00
他の回答は正しいですが、Java.timeフレームワークによって時代遅れになった古い日時クラスを使用してください。
Java.timeフレームワークは、Java 8以降に組み込まれています。 Java.time機能の多くは、Java 6および7( ThreeTen-Backport )にバックポートされ、さらにAndroid( ThreeTenABP )に適合しています。
まず、ISO 8601形式の標準バージョンに準拠するように入力文字列を変更します。標準の ISO 8601 形式は、日時値を表す文字列の解析/生成のために、Java.timeクラスでデフォルトで使用されます。途中のSPACEをT
に置き換える必要があります。
String input = "2008-01-01 13:15:00".replace( " " , "T" ); // → 2008-01-01T13:15:00
これで LocalDateTime
として解析できます。ここで、「ローカル」は特定のローカリティがないことを意味します。入力に offset-from-UTC またはタイムゾーン情報がありません。
LocalDateTime ldt = LocalDateTime.parse( input );
ldt.toString()…2008-01-01T13:15:00
時刻もタイムゾーンも気にしない場合は、 LocalDate
に変換します。
LocalDate ld = ldt.toLocalDate();
ld.toString()…2008-01-01
代わりに時刻を1日の最初の瞬間に設定する場合は、 ZonedDateTime
クラスを使用し、LocalDate
オブジェクトに変換して、その atStartOfDay
メソッドを呼び出します。夏時間またはその他の異常のために、最初の瞬間は00:00:00
の時間ではない可能性があることに注意してください。
タイムゾーンは非常に重要です。これは、特定の瞬間について、日付が世界中でゾーンによって異なるためです。たとえば、パリの真夜中から数分後はパリジャンにとって新しい日ですが、カナダ人にとってはモントリオールではまだ「昨日」です。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );
LocalDate ldFromZdt = zdt.toLocalDate();
ZonedDateTime zdtStartOfDay = ldFromZdt.atStartOfDay( zoneId );
zdtStartOfDay.toString()…2008-01-01T00:00:00-05:00 [アメリカ/モントリオール]
UTC タイムゾーンのレンズを通してその瞬間を確認するには、 Instant
オブジェクトを抽出します。 ZonedDateTime
とInstant
は、タイムライン上の同じ瞬間を表しますが、2つの異なる 壁時計時間 として表示されます。
Instant
はJava.timeの基本的なビルディングブロッククラスであり、常に定義によりUTCです。通常、UTCでビジネスロジック、データストレージ、およびデータ交換を行う必要があるため、このクラスを頻繁に使用します。
Instant instant = zdtStartOfDay.toInstant();
instant.toString()…2008-01-01T05:00:00Z
真夜中の行程ではなく午前5時です。標準形式では、末尾のZ
はZulu
の略で、「UTC」を意味します。
Java.time フレームワークは、Java 8以降に組み込まれています。これらのクラスは、 Java.util.Date
、 Calendar
、& SimpleDateFormat
などの厄介な古い レガシー 日時クラスに取って代わります。
メンテナンスモード になった Joda-Time プロジェクトは、 Java.time クラスへの移行を推奨しています。
詳細については、 Oracle Tutorial を参照してください。また、多くの例と説明についてはStack Overflowを検索してください。仕様は JSR 31 です。
Java.timeオブジェクトをデータベースと直接交換できます。 JDBC 4.2 以降に準拠する JDBCドライバー を使用します。文字列やJava.sql.*
クラスは必要ありません。
Java.timeクラスはどこで入手できますか?
ThreeTen-Extra プロジェクトは、追加のクラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性のある証明の場です。 Interval
、 YearWeek
、 YearQuarter
、 more などの便利なクラスがあります。
問題は矛盾しています。時刻なしの日付を要求しますが、00:00:00
の時刻を持つ例を表示します。
UPDATE:Joda-Time プロジェクトは メンテナンスモード になり、チームは移行をアドバイスしています Java.time クラスへ。 Java.timeソリューションについては、 my other Answer を参照してください。
代わりに時刻を1日の最初の瞬間に設定する場合は、Joda-Timeライブラリで DateTime
オブジェクトを使用し、その withTimeAtStartOfDay
メソッドを呼び出します。夏時間やその他の異常のために、最初の瞬間は00:00:00
の時間ではないことに注意してください。
ただclear()
冗長フィールド。
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.clear(Calendar.MINUTE);
calendar.clear(Calendar.SECOND);
calendar.clear(Calendar.MILLISECOND);
Date truncatedDate = calendar.getTime();
Java 8以降では、truncatedTo
のLocalDateTime
メソッドを使用することをお勧めします。例:
LocalDateTime.now().truncatedTo(ChronoUnit.DAYS)
Calendar クラスのset()
メソッドを使用して、HOUR_OF_DAY, MINUTE, SECOND
およびMILLISECOND
フィールドをゼロに設定します。
これにより、タイムゾーンの問題を回避できます。
public static Date truncDate(Date date) {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
Java Date
オブジェクトはタイムスタンプ値ですが、トランケート中にローカルタイムゾーンに変換されるため、UTCタイムゾーンから値を期待する場合は驚くべき値を取得します。
新しい「改善された」カレンダーコンストラクターが、「ひどい」古い日付のようなミリ秒の整数をとらないことに本当に悩まされました。それから私は本当に交差し、これを書いた:
long stuffYou = startTime.getTimeInMillis() % 1000;
startTime.setTimeInMillis(startTime.getTimeInMillis() - stuffYou);
当時は「もの」という言葉を使用していませんでしたが、次の幸福を発見しました。
startTime.set(Calendar.MILLISECOND, 0);
しかし、私はまだそれについてかなり交差しています。
Java 8+を使用している場合、時間なしで日付を取得する簡単な方法は次のとおりです。Dateの代わりにJava.time.LocalDateタイプを使用します。
LocalDate now = LocalDate.now();
System.out.println(now.toString());
出力:
2019-05-30
https://docs.Oracle.com/javase/8/docs/api/Java/time/LocalDate.html
応答が遅れるかもしれませんが、ライブラリを使用せずに1行で実行する方法を次に示します。
new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(YOUR_TIMESTAMP))
カレンダーを使用したすべての回答については、代わりにこのように使用する必要があります
public static Date truncateDate(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY));
c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE));
c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND));
c.set(Calendar.MILLISECOND, c.getActualMinimum(Calendar.MILLISECOND));
return c.getTime();
}
しかし、私はこれを好む:
public static Date truncateDate(Date date) {
return new Java.sql.Date(date.getTime());
}
私はこのような問題を修正しました(東部8ゾーン(北京時間)):
private Date getTruncatedDate(Date d) {
if (d == null) {
return null;
}
long h = 60 * 60 * 1000L;
long dateStamp = d.getTime() - (d.getTime() + 8 * h) % (24 * h);
return new Date(dateStamp);
}
まず、タイムスタンプとは何かを明確にする必要があります。タイムスタンプは、GMTの1970年1月1日00:00:00(UTCと同じ)、または1970年1月1日木曜日08:00:00 CST 1970から現在までの合計ミリ秒です。
注意:タイムスタンプはタイムゾーンに依存しません。
したがって、異なるタイムゾーンで次のステートメントを使用しても同じ結果が得られます。
System.out.println(new Date().getTime());
そして
System.out.println(new Date(0));
異なるタイムゾーンで異なる時間情報を出力します。PCタイムゾーンをUTCに設定すると、
Thu Jan 01 00:00:00 UTC 1970
ただし、タイムゾーンを(UTC +8:00)北京、重慶、香港、ウルムクに設定すると、次のようになります。
Thu Jan 01 08:00:00 CST 1970
Javaはタイムスタンプを取得し、タイムゾーンに従って日付と時刻の情報を表示します。
Javaがさまざまなタイムゾーンで日付と時刻の情報を表示する方法の概要については、時刻情報を変換する方法は簡単です。タイムスタンプを取得し、時間情報を切断するときにタイムゾーンを考慮する必要があります。次に、カットタイムスタンプ(日付スタンプと呼ぶことができます)を使用して新しいDateオブジェクトを作成できます。Javaは、日付情報を表示するときにタイムゾーンを補正します。
東部8ゾーン(北京時間)と同様に、北京時間はGMTより8時間早いため、モジュロ演算を行う場合はさらに8時間を差し引く必要があります。つまり、GMT時間を最初に取得する必要があります。その後、Javaは、PCのタイムゾーン設定に基づいて時間を表示するときに8時間を追加します。
タイムゾーンの問題はあいまいであり、長い間私を困惑させます。今、私はそれを明確にします。希望が役立ちます。
2018-01-04以下の方法も機能します。
private Date getTruncatedDate2(Date d) {
Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(d);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
Joda-Time バージョン2.0以降では、LocalDate.toDate()
を使用できます。
単に
// someDatetime is whatever Java.util.Date you have.
Date someDay = new LocalDate(someDatetime).toDate();