我有一个包含日期和时间信息的Java Date对象。我想写一个方法来切断时间信息,截断小时 - 分钟 - 秒,所以我只剩下日期。
示例输入:
2008-01-01 13:15:00
预期产出:
2008-01-01 00:00:00
你有小费吗?我尝试过这样的事情:
(timestamp / (24 * 60 * 60 * 1000)) * (24 * 60 * 60 * 1000)
但是我遇到了时区的问题。
答案 0 :(得分:162)
推荐进行日期/时间操作的方法是使用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();
答案 1 :(得分:131)
您是否查看了Apache Commons Lang中的DateUtils truncate方法?
Date truncatedDate = DateUtils.truncate(new Date(), Calendar.DATE);
将删除时间元素。
答案 2 :(得分:40)
你看过Joda了吗?这是一个很多更简单,更直观的方式来处理日期和时间。例如,您可以在(例如)LocalDateTime和LocalDate个对象之间轻松转换。
e.g。 (以说明API)
LocalDate date = new LocalDateTime(milliseconds).toLocalDate()
此外,它解决了日期/时间格式化程序的一些线程安全问题,强烈建议您使用Java中的任何日期/时间问题。
答案 3 :(得分:24)
根据Java 8及更高版本中内置的java.time类,快速更新。
LocalDateTime
有一个truncatedTo
方法可以有效地解决您在此处讨论的内容:
LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES)
这将仅将当前时间表示为分钟:
2015-03-05T11:47
您可以使用任何ChronoUnit
(或实际上任何TemporalUnit
)来执行截断。
答案 4 :(得分:23)
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();
答案 5 :(得分:21)
使用Joda,您可以轻松获得预期日期。
从版本2.7开始(可能是因为某些以前的版本大于2.2),作为评论者注释,toDateMidnight
已被弃用,或者恰当地命名为withTimeAtStartOfDay()
,方便
DateTime.now().withTimeAtStartOfDay()
可能的。
增加了一种更好的API。
对于旧版本,您可以
new DateTime(new Date()).toDateMidnight().toDate()
答案 6 :(得分:6)
使用Apache的DateUtils,使用truncate,如下所示:
DateUtils.truncate(Calendar.getInstance().getTime(), Calendar.DATE);
答案 7 :(得分:6)
对于时间戳:
timestamp -= timestamp % (24 * 60 * 60 * 1000)
答案 8 :(得分:6)
我使用新的java 8 API进行了截断。我遇到了一个奇怪的事情,但总的来说它会被截断......
Instant instant = date.toInstant();
instant = instant.truncatedTo(ChronoUnit.DAYS);
date = Date.from(instant);
答案 9 :(得分:4)
来自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
答案 10 :(得分:3)
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.
.toString() // Generate a String in standard ISO 8601 format, wisely extended to append the name of the time zone in square brackets.
2008-01-01T00:00 + 01:00 [欧洲/巴黎]
要以所需格式生成字符串,请传递DateTimeFormatter
。
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.
.format( // Generate a String representing the object’s value.
DateTimeFormatter.ISO_LOCAL_DATE_TIME // Built-in predefined formatter close to what you want.
)
.replace( "T" , " " ) // Replace the standard’s use of a 'T' in the middle with your desired SPACE character.
2008-01-01 00:00:00
其他答案是正确的,但现在使用旧的日期时间类,现在已经过时了java.time框架。
java.time框架内置于Java 8及更高版本中。许多java.time功能都被反向移植到Java 6& 7(ThreeTen-Backport)并进一步适应Android(ThreeTenABP)。
首先更改输入字符串以符合ISO 8601格式的规范版本。默认情况下,java.time类中使用标准ISO 8601格式来解析/生成表示日期时间值的字符串。我们需要用T
替换中间的空格。
String input = "2008-01-01 13:15:00".replace( " " , "T" ); // → 2008-01-01T13:15:00
现在我们可以将其解析为LocalDateTime
,其中“Local”表示没有特定的位置。输入缺少任何offset-from-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
方法。请注意,由于夏令时或其他异常,第一时刻可能不是时间00:00:00
。
时区至关重要,因为在任何特定时刻,日期因地区而异。例如,在巴黎午夜过后的一段时间对于巴黎人来说是新的一天,但对于加拿大人来说仍然是蒙特利尔的“昨天”。
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
都代表时间轴上的相同时刻,但显示为两个不同的wall-clock times。
Instant
是java.time中的基本构造块类,根据定义始终为UTC。经常使用此类,因为您通常应该使用UTC进行业务逻辑,数据存储和数据交换。
Instant instant = zdtStartOfDay.toInstant();
instant.toString()... 2008-01-01T05:00:00Z
我们看到凌晨5点,而不是午夜时分。在标准格式中,末尾的Z
是Zulu
的缩写,表示“UTC”。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 11 :(得分:2)
使用Calendar班级的set()
方法将HOUR_OF_DAY, MINUTE, SECOND
和MILLISECOND
字段设置为零。
答案 12 :(得分:2)
这个问题是矛盾的。它要求没有时间的日期,但会显示时间为00:00:00
的示例。
更新 Joda-Time项目现在位于maintenance mode,团队建议迁移到java.time课程。有关java.time解决方案,请参阅my other Answer。
如果您希望将时间设置为当天的第一时刻,请使用Joda-Time库上的DateTime
对象并调用其withTimeAtStartOfDay
方法。请注意,由于夏令时或其他异常,第一时刻可能不是时间00:00:00
。
答案 13 :(得分:1)
令我非常恼火的是,新的“改进的”日历构造函数没有像“糟糕的”旧日期那样使用int毫秒。 然后我真的交叉并写了这个:
long stuffYou = startTime.getTimeInMillis() % 1000;
startTime.setTimeInMillis(startTime.getTimeInMillis() - stuffYou);
我当时没有使用“东西”这个词,但是 然后我发现了这个的快乐:
startTime.set(Calendar.MILLISECOND, 0);
但我仍然对它很不满意。
答案 14 :(得分:1)
您可以这样做以避免时区问题:
public static Date truncDate(Date date) {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
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);
return cal.getTime();
}
尽管Java Date
对象是时间戳值,但在截断期间,它将被转换为本地时区,因此如果您期望UTC时区的值,您将获得惊人的值。
答案 15 :(得分:1)
只有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();
答案 16 :(得分:0)
从版本2.0开始Joda-Time,您可以使用LocalDate.toDate()
。
简单地
// someDatetime is whatever java.util.Date you have.
Date someDay = new LocalDate(someDatetime).toDate();
答案 17 :(得分:0)
对于使用日历的所有答案,您应该像这样使用它
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());
}
答案 18 :(得分:0)
可能是一个迟到的回复,但这是一种在不使用任何库的情况下在一行中完成它的方法:
new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(YOUR_TIMESTAMP))
答案 19 :(得分:0)
我解决了这个问题(东部八区(北京时间)):
private Date getTruncatedDate(Date d) {
if (d == null) {
return null;
}
long h = 60 * 60 * 1000L;
long dateStamp = d.getTime() - (d.getTime() + 8 * h) % (24 * h);
return new Date(dateStamp);
}
首先,你应该清楚什么是时间戳。 时间戳是格林威治标准时间1970年1月1日00:00:00(与UTC相同)或1970年1月1日08:00:00到现在的总时间。
请记住:时间戳与时区无关。
因此,您可以在不同的时区使用以下语句获得相同的结果:
System.out.println(new Date().getTime());
并且
System.out.println(new Date(0));
在不同时区打印不同的时间信息: 如果您将您的电脑时区设置为UTC,则
Thu Jan 01 00:00:00 UTC 1970
但如果你将时区设定为(UTC +8:00)北京,重庆,香港,乌鲁木齐,你会得到:
Thu Jan 01 08:00:00 CST 1970
Java获取时间戳,然后根据时区显示日期和时间信息。
为了介绍Java如何在不同时区显示日期和时间信息,如何轻松转换时间信息。你应该得到时间戳,并在切断时间信息时考虑时区。然后你可以创建一个带有剪切时间戳的新Date对象(我们可以称之为日期戳),java会在显示日期信息时补偿时区。
与东部八区(北京时间)一样,北京时间早于GMT 8小时,因此在进行模运算时应减去8小时以上。 这就是说,你应该首先获得GMT时间,然后根据你电脑的时区设置,Java将在显示时间上增加8小时。
时区问题晦涩难懂,也困扰了我很久。现在我说清楚了。 希望有所帮助。
2018年1月4日 以下方法也有效。
private Date getTruncatedDate2(Date d) {
Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(d);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
答案 20 :(得分:0)
如果您使用的是Java 8+,这是一种无需时间即可获取日期的简单方法:使用 java.time.LocalDate 类型而不是Date。
LocalDate now = LocalDate.now();
System.out.println(now.toString());
输出:
2019-05-30
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html