在 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 所说的一样。
假设您的“时间戳”是 java.util.Date,它表示为自纪元开始(1970 年 1 月 1 日)以来的毫秒数,您可以执行以下算术:
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));
做这个
import org.apache.commons.lang.time.DateUtils;
Date myDate = new Date();
System.out.println(myDate);
System.out.println(DateUtils.truncate(myDate, Calendar.DATE));
输出是
2014 年 3 月 19 日星期三14:16:47 PDT 2014 年
3 月 19 日星期三 00:00:00 PDT
由于我没有做太多的 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 中当前配置的时区中获取当前日期和时间 (into currentDateand currentTime) 或通知的某个日期和时间 (into informedDateand )。informedTime
下面的代码还通知通知的日期/时间是否在未来(变量schedulable)。
请注意 Joda Time 不支持闰秒。因此,您可能会偏离真实值大约 26 或 27 秒。这可能要在未来 50 年才能解决,到时累积误差会接近 1 分钟,人们才会开始关心它。
另见: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;
}
}
这是一个带有主要示例的简单函数:
import java.util.Calendar;
import java.util.Date;
public class Util {
/**
* Returns an imprecise date/timestamp.
* @param date
* @return the timestamp with zeroized seconds/milliseconds
*/
public static Date getImpreciseDate(Date date) {
Calendar cal = Calendar.getInstance(); // get calendar instance
cal.setTime(date);// set cal to date
cal.set(Calendar.SECOND, 0); // zeroize seconds
cal.set(Calendar.MILLISECOND, 0); // zeroize milliseconds
return cal.getTime();
}
public static void main(String[] args){
Date now = new Date();
now.setTime(System.currentTimeMillis()); // set time to now
System.out.println("Precise date: " + Util.getImpreciseDate(now));
System.out.println("Imprecise date: " + Util.getImpreciseDate(now));
}
}