在 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 currentDate
and currentTime
) 或通知的某个日期和时间 (into informedDate
and )。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));
}
}