在 Java 中重置时间戳的时间部分
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/227007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Resetting the time part of a timestamp in Java
提问by Vijay Dev
In Java, given a timestamp, how to reset the time part alone to 00:00:00 so that the timestamp represents the midnight of that particular day ?
在 Java 中,给定一个时间戳,如何将时间部分单独重置为 00:00:00,以便时间戳表示该特定日期的午夜?
In T-SQL, this query will do to achieve the same, but I don't know how to do this in Java.
在 T-SQL 中,此查询将实现相同的目的,但我不知道如何在 Java 中执行此操作。
SELECT CAST( FLOOR( CAST(GETDATE() AS FLOAT ) ) AS DATETIME) AS 'DateTimeAtMidnight';
SELECT CAST( FLOOR( CAST(GETDATE() AS FLOAT ) ) AS DATETIME) AS 'DateTimeAtMidnight';
采纳答案by Alex Miller
You can go Date->Calendar->set->Date:
你可以去日期->日历->设置->日期:
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
I love Java dates.
我喜欢 Java 日期。
Note that if you're using actual java.sql.Timestamps, they have an extra nanos field. Calendar of course, knows nothing of nanos so will blindly ignore it and effectively drop it when creating the zeroedDate at the end, which you could then use to create a new Timetamp object.
请注意,如果您使用的是实际的 java.sql.Timestamps,它们会有一个额外的 nanos 字段。当然,日历对 nanos 一无所知,因此在最后创建 zeroedDate 时会盲目地忽略它并有效地删除它,然后您可以使用它来创建新的 Timetamp 对象。
I should also note that Calendar is not thread-safe, so don't go thinking you can make that a static single cal instance called from multiple threads to avoid creating new Calendar instances.
我还应该注意到 Calendar 不是线程安全的,所以不要认为您可以从多个线程调用静态单个 cal 实例以避免创建新的 Calendar 实例。
回答by thoroughly
Assuming your "timestamp" is a java.util.Date, which is represented as the number of milliseconds since the beginning of the epoch (Jan 1, 1970), you can perform the following arithmetic:
假设您的“时间戳”是一个 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);
}
回答by Jan Gressmann
Since I don't do much DateTime manipulation, this might not be the best way to do it. I would spawn a Calendar and use the Date as source. Then set hours, minutes and seconds to 0 and convert back to Date. Would be nice to see a better way, though.
由于我不做太多的 DateTime 操作,这可能不是最好的方法。我会生成一个日历并使用日期作为源。然后将小时、分钟和秒设置为 0 并转换回日期。不过,如果能看到更好的方法就好了。
回答by Domchi
Using Calendar.set() would certanly be "by the book" solution, but you might also use java.sql.Date:
使用 Calendar.set() 肯定是“书本”的解决方案,但您也可以使用 java.sql.Date:
java.util.Date originalDate = new java.util.Date();
java.sql.Date wantedDate = new java.sql.Date(originalDate.getTime());
That would do exactly what you want since:
这将完全符合您的要求,因为:
To conform with the definition of SQL DATE, the millisecond values wrapped by a java.sql.Date instance must be 'normalized' by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated.
为了符合 SQL DATE 的定义,java.sql.Date 实例包装的毫秒值必须通过在实例关联的特定时区中将小时、分钟、秒和毫秒设置为零来“标准化” .
Since java.sql.Date extends java.util.Date, you can freely use it as such. Be aware that wantedDate.getTime() will retrieve original timestamp though - that's why you don't want to create another java.util.Date from java.sql.Date!
由于 java.sql.Date 扩展了 java.util.Date,因此您可以自由地使用它。请注意,wantedDate.getTime() 将检索原始时间戳 - 这就是您不想从 java.sql.Date 创建另一个 java.util.Date 的原因!
回答by ScArcher2
If you're using commons lang you can call DateUtils.truncate
. Here's the javadoc documentation.
如果您使用的是 commons lang,则可以调用DateUtils.truncate
. 这是javadoc 文档。
It does the same thing @Alex Miller said to do.
它做同样的事情@Alex Miller 说要做。
回答by Torben Kohlmeier
I prefer this solution:
我更喜欢这个解决方案:
GregorianCalendar now = new GregorianCalendar();
GregorianCalendar calendar = new GregorianCalendar(
now.get(GregorianCalendar.YEAR), now.get(GregorianCalendar.MONTH),
now.get(GregorianCalendar.DAY_OF_MONTH));
回答by Ziya
Do this
做这个
import org.apache.commons.lang.time.DateUtils;
Date myDate = new Date();
System.out.println(myDate);
System.out.println(DateUtils.truncate(myDate, Calendar.DATE));
and the output is
输出是
Wed Mar 19 14:16:47 PDT 2014
Wed Mar 19 00:00:00 PDT 2014
2014 年
3 月 19日星期三14:16:47 PDT 2014 年3 月 19日星期三 00:00:00 PDT
回答by Richard Gomes
Find below a solution which employs Joda Time and supports time zones.
So, you will obtain the current date and time (into currentDate
and currentTime
) or some date and time you inform (into informedDate
and informedTime
) in the currently configured timezone in the JVM.
在下面找到一个使用 Joda 时间并支持时区的解决方案。因此,您将在 JVM 中当前配置的时区中获取当前日期和时间(进入currentDate
和currentTime
)或通知(进入informedDate
和informedTime
)的某个日期和时间。
The code below also informs if the informed date/time is in future (variable schedulable
).
下面的代码还通知通知的日期/时间是否在未来(变量schedulable
)。
Please notice that Joda Time does not support leap seconds. So, you can be some 26 or 27 seconds off the true value. This probably will only be solved in the next 50 years, when the accumulated error will be closer to 1 min and people will start to care about it.
请注意 Joda Time 不支持闰秒。因此,您可能与真实值相差 26 或 27 秒。这可能要在未来 50 年才能解决,届时累积误差将接近 1 分钟,人们将开始关心它。
See also: https://en.wikipedia.org/wiki/Leap_second
另见: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;
}
}
回答by MAbraham1
Here's a simple function with a main example:
这是一个带有主要示例的简单函数:
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));
}
}
回答by Sabir Khan
Just trying to put an answer for Java-8 , though answers using Calendar
are valid too but lots of folks are not using that class anymore.
只是想为 Java-8 提供一个答案,尽管使用Calendar
的答案也有效,但很多人不再使用该类了。
Refer SO Answers this& thisto understand conversions between java.time.ZonedDateTime
& java.sql.Timestamp
请参阅 SO Answers this& this以了解java.time.ZonedDateTime
&之间的转换java.sql.Timestamp
then you can simply truncate ZonedDateTime
on days & reconvert back to Timestamp
然后你可以简单地截断ZonedDateTime
几天并重新转换回Timestamp
Timestamp.valueOf(ZonedDateTime.now().truncatedTo(ChronoUnit.DAYS).toLocalDateTime())