39

在 Java 中,给定一个时间戳,如何将时间部分单独重置为 00:00:00,以便时间戳代表该特定日期的午夜?

在 T-SQL 中,此查询将实现相同的功能,但我不知道如何在 Java 中执行此操作。

SELECT CAST( FLOOR( CAST(GETDATE() AS FLOAT ) ) AS DATETIME) AS 'DateTimeAtMidnight';

4

10 回答 10

81

你可以去日期->日历->设置->日期:

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 实例。

于 2008-10-22T18:38:31.013 回答
19

如果您使用的是 commons lang,您可以调用DateUtils.truncate. 这是javadoc 文档

它和@Alex Miller 所说的一样。

于 2008-10-22T21:22:41.307 回答
7

假设您的“时间戳”是 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);
}
于 2008-10-22T18:37:47.940 回答
4

我更喜欢这个解决方案:

GregorianCalendar now = new GregorianCalendar();
GregorianCalendar calendar = new GregorianCalendar(
              now.get(GregorianCalendar.YEAR), now.get(GregorianCalendar.MONTH), 
              now.get(GregorianCalendar.DAY_OF_MONTH));
于 2012-11-19T21:57:19.080 回答
4

做这个

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

于 2014-03-19T21:21:50.257 回答
1

由于我没有做太多的 DateTime 操作,这可能不是最好的方法。我会生成一个日历并将日期用作源。然后将小时、分钟和秒设置为 0 并转换回日期。不过,很高兴看到更好的方法。

于 2008-10-22T18:38:38.767 回答
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 的原因!

于 2008-10-22T19:21:25.810 回答
0

在下面找到使用 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;
    }
}
于 2015-07-10T12:20:07.887 回答
0

这是一个带有主要示例的简单函数:

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));
}
}
于 2017-01-18T15:22:21.830 回答
0

只是试图为 Java-8 提供答案,尽管使用的答案Calendar也有效,但很多人不再使用该类了。

请参阅 SO Answers this & this以了解java.time.ZonedDateTime&之间的转换java.sql.Timestamp

然后你可以简单地截断ZonedDateTime几天并重新转换回Timestamp

Timestamp.valueOf(ZonedDateTime.now().truncatedTo(ChronoUnit.DAYS).toLocalDateTime())
于 2019-08-20T13:03:07.110 回答