Java Date截断时间信息
我有一个包含date和时间信息的Javadate对象。 我想写一个方法,切断时间信息,所以我只剩下date。
示例input:
2008-01-01 13:15:00
预期产出:
2008-01-01 00:00:00
你有小费吗? 我试着做这样的事情:
(timestamp / (24 * 60 * 60 * 1000)) * (24 * 60 * 60 * 1000)
但是我遇到了这个时区的问题。
date/时间操作的推荐方法是使用Calendar
对象:
Calendar cal = Calendar.getInstance(); // locale-specific cal.setTime(dateObject); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); long time = cal.getTimeInMillis();
你看过Apache Commons Lang中的DateUtils truncate方法吗?
Date truncatedDate = DateUtils.truncate(new Date(), Calendar.DATE);
将删除时间元素。
你看过乔达吗? 这是一个更容易,更直观的方式来处理date和时间。 例如,你可以在LocalDateTime和LocalDate对象之间转换(比如说)。
例如(来说明API)
LocalDate date = new LocalDateTime(milliseconds).toLocalDate()
此外,它还解决了date/时间格式化程序中的一些线程安全问题,强烈build议在Java中处理任何date/时间问题。
Date date = new Date(); Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); date = cal.getTime();
随着乔达你可以很容易地得到预期的date。
从版本2.7开始(也许从以前的一些版本大于2.2开始),正如一位评论者指出的, toDateMidnight
已经被弃用,或者被适当地命名为withTimeAtStartOfDay()
,使得方便
DateTime.now().withTimeAtStartOfDay()
可能。
好处添加了一个更好的方法API。
用旧版本,你可以做
new DateTime(new Date()).toDateMidnight().toDate()
根据现在内置于Java 8及更高版本中的java.time类,仅仅是一个快速更新。
LocalDateTime
有一个truncatedTo
方法,可以有效地解决你在这里讨论的问题:
LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES)
这将只将当前时间表示为几分钟:
2015-03-05T11:47
您可以使用任何ChronoUnit
(或实际上任何TemporalUnit
)来执行截断。
从Apache使用DateUtils,截断,如下所示:
DateUtils.truncate(Calendar.getInstance().getTime(), Calendar.DATE);
对于时间戳:
timestamp -= timestamp % (24 * 60 * 60 * 1000)
我用新的java8 API做了截断。 我面对一个奇怪的事情,但一般来说它是截断的…
Instant instant = date.toInstant(); instant = instant.truncatedTo(ChronoUnit.DAYS); date = Date.from(instant);
来自java.util.Date JavaDocs:
Date类表示特定的即时时间,毫秒精度
并从java.sql.Date JavaDocs:
为了符合SQL DATE的定义,由java.sql.Date实例包装的毫秒值必须通过将与实例关联的特定时区中的小时,分钟,秒和毫秒设置为零来“标准化” 。
所以,如果你不需要时间部分,最好的方法是使用java.sql.Date
java.util.Date utilDate = new java.util.Date(); java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());
输出是:
java.util.Date : Thu Apr 26 16:22:53 PST 2012 java.sql.Date : 2012-04-26
这个问题是矛盾的。 它要求一个没有时间的date,但是显示一个时间为00:00:00
的例子。
乔达时间
更新: Joda-Time项目现在处于维护模式 ,团队build议迁移到java.time类。 看到我的另一个 java.time解决scheme的答案 。
如果您希望将时间设置为一天中的第一个时间,请在Joda-Time库上使用DateTime
对象,并调用withTimeAtStartOfDay
方法。 请注意,由于夏令时或其他exception情况,第一时刻可能不是00:00:00
的时间。
使用Calendar类的set()
方法将HOUR_OF_DAY, MINUTE, SECOND
和MILLISECOND
字段设置为零。
只需clear()
多余的字段。
Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.clear(Calendar.MINUTE); calendar.clear(Calendar.SECOND); calendar.clear(Calendar.MILLISECOND); Date truncatedDate = calendar.getTime();
这让我非常恼火,新的“改进”的日历构造函数不会像“糟糕的”旧的date一样毫秒级的int。 然后我真的交叉,写下这个:
long stuffYou = startTime.getTimeInMillis() % 1000; startTime.setTimeInMillis(startTime.getTimeInMillis() - stuffYou);
我当时并没有使用“东西”这个词,但后来我发现了这样的幸福:
startTime.set(Calendar.MILLISECOND, 0);
但是我还是十分的交叉
可能是一个迟到的反应,但这是一个方法来做到这一行,而不使用任何库:
new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(YOUR_TIMESTAMP))
对于使用日历的所有答案,您应该像这样使用它
public static Date truncateDate(Date date) { Calendar c = Calendar.getInstance(); c.setTime(date); c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY)); c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE)); c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND)); c.set(Calendar.MILLISECOND, c.getActualMinimum(Calendar.MILLISECOND)); return c.getTime(); }
但我更喜欢这个:
public static Date truncateDate(Date date) { return new java.sql.Date(date.getTime()); }
TL;博士
LocalDateTime.parse( // Lacking an offset or time zone, parse as a `LocalDateTime`. *Not* a specific moment in time. "2008-01-01 13:15:00".replace( " " , "T" ) // Alter input string to comply with ISO 8601 standard format. ) .toLocalDate() // Extract a date-only value. .atStartOfDay( // Do not assume the day starts at 00:00:00. Let class determine start-of-day. ZoneId.of( "Europe/Paris" ) // Determining a specific start-of-day requires a time zone. ) // Result is a `ZonedDateTime` object. At this point we have a specific moment in time, a point on the timeline.
细节
其他答案是正确的,但使用现在由java.time框架过时的旧date时间类。
java.time
java.time框架内置于Java 8及更高版本中。 许多java.timefunction被移植到Java 6&7( ThreeTen-Backport ),并进一步适用于Android( ThreeTenABP )。
首先改变inputstring以符合ISO 8601格式的规范版本。 在java.time类中默认使用标准的ISO 8601格式来parsing/生成表示date时间值的string。 我们需要用T
来replace那个SPACE。
String input = "2008-01-01 13:15:00".replace( " " , "T" ); // → 2008-01-01T13:15:00
现在我们可以将其parsing为LocalDateTime
,其中“Local”表示没有特定的地方。 input缺less从UTC或时区信息的任何偏移量 。
LocalDateTime ldt = LocalDateTime.parse( input );
ldt.toString()… 2008-01-01T13:15:00
如果您不关心时间或时区,则转换为LocalDate
。
LocalDate ld = ldt.toLocalDate();
ld.toString()… 2008-01-01
第一天的一刻
如果您希望将时间设置为一天中的第一个时间,请使用ZonedDateTime
类,然后转换为LocalDate
对象以调用其atStartOfDay
方法。 请注意,由于夏令时或其他exception情况,第一时刻可能不是00:00:00
的时间。
时区是至关重要的,因为在任何特定的时刻,date在世界范围内随区域而变化。 例如,在巴黎午夜过后的几分钟,对巴黎人来说是新的一天,但对于加拿大人来说,在蒙特利尔仍然是“昨天”。
ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ldt.atZone( zoneId ); LocalDate ldFromZdt = zdt.toLocalDate(); ZonedDateTime zdtStartOfDay = ldFromZdt.atStartOfDay( zoneId );
zdtStartOfDay.toString()… 2008-01-01T00:00:00-05:00 [美国/蒙特利尔]
世界标准时间
要通过UTC时区的镜头看到这一刻,请提取Instant
对象。 ZonedDateTime
和Instant
都将表示时间轴上的同一时刻,但performance为两个不同的挂钟时间 。
Instant
是java.time中的基本构build块类,通常按照UTC定义。 经常使用这个类,因为通常应该使用UTC来进行业务逻辑,数据存储和数据交换。
Instant instant = zdtStartOfDay.toInstant();
instant.toString()… 2008-01-01T05:00:00Z
我们看到的是凌晨5点而不是午夜。 在标准格式中, Z
最后是Zulu
缩写,意思是“UTC”。
从版本2.0开始, Joda-Time可以使用LocalDate.toDate()
。
只是
// someDatetime is whatever java.util.Date you have. Date someDay = new LocalDate(someDatetime).toDate();