Java Date截止时间信息

时间:2009-12-15 15:55:21

标签: java date time timestamp

我有一个包含日期和时间信息的Java Date对象。我想写一个方法来切断时间信息,截断小时 - 分钟 - 秒,所以我只剩下日期。

示例输入:

2008-01-01 13:15:00

预期产出:

2008-01-01 00:00:00

你有小费吗?我尝试过这样的事情:

(timestamp / (24 * 60 * 60 * 1000)) * (24 * 60 * 60 * 1000)

但是我遇到了时区的问题。

21 个答案:

答案 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了吗?这是一个很多更简单,更直观的方式来处理日期和时间。例如,您可以在(例如)LocalDateTimeLocalDate个对象之间轻松转换。

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)

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.
.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.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

要通过UTC时区的镜头查看该时刻,请提取Instant个对象。 ZonedDateTimeInstant都代表时间轴上的相同时刻,但显示为两个不同的wall-clock times

Instant是java.time中的基本构造块类,根据定义始终为UTC。经常使用此类,因为您通常应该使用UTC进行业务逻辑,数据存储和数据交换。

Instant instant = zdtStartOfDay.toInstant();
  

instant.toString()... 2008-01-01T05:00:00Z

我们看到凌晨5点,而不是午夜时分。在标准格式中,末尾的ZZulu的缩写,表示“UTC”。

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance 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的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 11 :(得分:2)

使用Calendar班级的set()方法将HOUR_OF_DAY, MINUTE, SECONDMILLISECOND字段设置为零。

答案 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