Java では、タイムスタンプが与えられた場合、タイムスタンプがその特定の日の真夜中を表すように、時間部分だけを 00:00:00 にリセットする方法は?
T-SQL では、このクエリで同じことを達成できますが、Java でこれを行う方法がわかりません。
SELECT CAST( FLOOR( CAST(GETDATE() AS FLOAT ) ) AS DATETIME) AS 'DateTimeAtMidnight';
日付 - >カレンダー - >設定 - >日付に移動できます。
Date date = new Date(); // timestamp now
Calendar cal = Calendar.getInstance(); // get calendar instance
cal.setTime(date); // set cal to date
cal.set(Calendar.HOUR_OF_DAY, 0); // set hour to midnight
cal.set(Calendar.MINUTE, 0); // set minute in hour
cal.set(Calendar.SECOND, 0); // set second in minute
cal.set(Calendar.MILLISECOND, 0); // set millis in second
Date zeroedDate = cal.getTime(); // actually computes the new Date
私は Java の日付が大好きです。
実際の java.sql.Timestamps を使用している場合、追加の nanos フィールドがあることに注意してください。もちろん、Calendar は nanos について何も知らないので、盲目的に無視し、最後に zeroedDate を作成するときに効果的に削除します。これを使用して、新しい Timetamp オブジェクトを作成できます。
また、Calendar はスレッドセーフではないことにも注意してください。そのため、複数のスレッドから呼び出される静的な単一の cal インスタンスを作成して、新しい Calendar インスタンスの作成を回避できると考えないでください。
commons lang を使用している場合は、DateUtils.truncate
. これがjavadocのドキュメントです。
@Alex Millerが言ったことと同じことをします。
「タイムスタンプ」がエポックの開始 (1970 年 1 月 1 日) からのミリ秒数として表される java.util.Date であると仮定すると、次の計算を実行できます。
public static Date stripTimePortion(Date timestamp) {
long msInDay = 1000 * 60 * 60 * 24; // Number of milliseconds in a day
long msPortion = timestamp.getTime() % msInDay;
return new Date(timestamp.getTime() - msPortion);
}
私はこの解決策を好みます:
GregorianCalendar now = new GregorianCalendar();
GregorianCalendar calendar = new GregorianCalendar(
now.get(GregorianCalendar.YEAR), now.get(GregorianCalendar.MONTH),
now.get(GregorianCalendar.DAY_OF_MONTH));
私は DateTime 操作をあまりしないので、これは最善の方法ではないかもしれません。カレンダーを生成し、日付をソースとして使用します。次に、時、分、秒を 0 に設定し、日付に戻します。しかし、より良い方法が見られるのはいいことです。
Calendar.set()を使用することは、確かに「本による」解決策ですが、java.sql.Dateを使用することもできます。
java.util.Date originalDate = new java.util.Date();
java.sql.Date wantedDate = new java.sql.Date(originalDate.getTime());
それ以来、あなたが望むことを正確に行うでしょう:
SQL DATEの定義に準拠するには、java.sql.Dateインスタンスによってラップされるミリ秒値を、インスタンスが関連付けられている特定のタイムゾーンで時間、分、秒、およびミリ秒をゼロに設定することによって「正規化」する必要があります。 。
java.sql.Dateはjava.util.Dateを拡張するため、そのまま自由に使用できます。ただし、wantedDate.getTime()は元のタイムスタンプを取得することに注意してください。そのため、java.sql.Dateから別のjava.util.Dateを作成したくないのです。
Joda Time を採用し、タイム ゾーンをサポートするソリューションを以下に示します。したがって、JVM で現在構成されているタイムゾーンで、現在の日付と時刻 (currentDate
とcurrentTime
) または通知した日付と時刻 (informedDate
と) を取得します。informedTime
以下のコードは、通知された日付/時刻が未来であるかどうかも通知します (変数schedulable
)。
Joda Time はうるう秒をサポートしていないことに注意してください。したがって、実際の値から 26 ~ 27 秒ほどずれることがあります。これはおそらく、累積誤差が 1 分に近づき、人々がそれを気にし始める 50 年以内に解決されるでしょう。
参照: https://en.wikipedia.org/wiki/Leap_second
/**
* This class splits the current date/time (now!) and an informed date/time into their components:
* <lu>
* <li>schedulable: if the informed date/time is in the present (now!) or in future.</li>
* <li>informedDate: the date (only) part of the informed date/time</li>
* <li>informedTime: the time (only) part of the informed date/time</li>
* <li>currentDate: the date (only) part of the current date/time (now!)</li>
* <li>currentTime: the time (only) part of the current date/time (now!)</li>
* </lu>
*/
public class ScheduleDateTime {
public final boolean schedulable;
public final long millis;
public final java.util.Date informedDate;
public final java.util.Date informedTime;
public final java.util.Date currentDate;
public final java.util.Date currentTime;
public ScheduleDateTime(long millis) {
final long now = System.currentTimeMillis();
this.schedulable = (millis > -1L) && (millis >= now);
final TimeZoneUtils tz = new TimeZoneUtils();
final java.util.Date dmillis = new java.util.Date( (millis > -1L) ? millis : now );
final java.time.ZonedDateTime zdtmillis = java.time.ZonedDateTime.ofInstant(dmillis.toInstant(), java.time.ZoneId.systemDefault());
final java.util.Date zdmillis = java.util.Date.from(tz.tzdate(zdtmillis));
final java.util.Date ztmillis = new java.util.Date(tz.tztime(zdtmillis));
final java.util.Date dnow = new java.util.Date(now);
final java.time.ZonedDateTime zdtnow = java.time.ZonedDateTime.ofInstant(dnow.toInstant(), java.time.ZoneId.systemDefault());
final java.util.Date zdnow = java.util.Date.from(tz.tzdate(zdtnow));
final java.util.Date ztnow = new java.util.Date(tz.tztime(zdtnow));
this.millis = millis;
this.informedDate = zdmillis;
this.informedTime = ztmillis;
this.currentDate = zdnow;
this.currentTime = ztnow;
}
}
public class TimeZoneUtils {
public java.time.Instant tzdate() {
final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
return tzdate(zdtime);
}
public java.time.Instant tzdate(java.time.ZonedDateTime zdtime) {
final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
final java.time.Instant instant = zddate.toInstant();
return instant;
}
public long tztime() {
final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
return tztime(zdtime);
}
public long tztime(java.time.ZonedDateTime zdtime) {
final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
final long millis = zddate.until(zdtime, java.time.temporal.ChronoUnit.MILLIS);
return millis;
}
}
Java-8 の答えを出そうとしていますが、使用した答えCalendar
も有効ですが、多くの人がそのクラスをもう使用していません。
SO Answer this & thisjava.time.ZonedDateTime
を参照して、 &間の変換を理解してください。java.sql.Timestamp
ZonedDateTime
その後、単純に日数を切り捨てて再変換することができますTimestamp
Timestamp.valueOf(ZonedDateTime.now().truncatedTo(ChronoUnit.DAYS).toLocalDateTime())