java check一个Date实例有时间部分

时间:2015-12-12 12:09:38

标签: java date datetime

我的班级中有一个Date字段,可以有两种类型的值:有和没有时间。这样的事情:2015-01-012015-01-01 12:00:00。我想从我的日期制作格式化的字符串。我知道我可以使用SimpleDateFormat课来做这件事,但我不知道格式。事实上,如果我的日期有时间部分,我必须使用yyyy-MM-dd HH:mm:ss格式,如果我的日期没有时间部分,我必须使用yyyy-MM-dd格式。我的问题是,在格式化之前是否有检查日期的时间段?

这是我的代码:

private SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);

.....

private String formatDate(Date date){
     //I need to something like this:
     if(/* `date` has time part */){
          return dateTimeFormat.format(date);
     }

     else{
          return dateFormat.format(date);
     }
}

4 个答案:

答案 0 :(得分:2)

您无法可靠地执行此操作,因为一旦创建了Date对象,它就会以毫秒为单位表示,其中包括特定时间。因此,您无法知道对象是如何构建的以及是否设置了特定时间。

解决方法是检查小时,分钟和秒是否设置为零。请注意,将日期解析为"yyyy-MM-dd HH:mm:ss"的可能性很小,但所有这些值都设置为0,因为时间确实是00:00:00。但是,这个概率等于1 / (24 * 60 * 60) = 0.00001157407,所以我假设你可以接受它。

答案 1 :(得分:2)

大混乱

如其他答案所示,与Java捆绑在一起的旧日期时间类如java.util.Date和java.sql.Date是一团糟。由于糟糕的设计决定,他们被赶到了市场。具体来说,java.util.Date表示日期和时间,而它的子类java.sql.Date假装没有时间但实际上没有。该文档解释说,您应该忽略这种继承关系以帮助维持幻觉。不好。

java.time

整个混乱已经被Java 8及更高版本中内置的java.time框架所取代。新课程的灵感来自非常成功的Joda-Time框架,旨在作为其继承者,在概念上类似但重新设计。由JSR 310定义。由ThreeTen-Extra项目扩展。请参阅Tutorial

日期 - 仅

新课程中有LocalDate。这是与Java捆绑的第一个类,仅用于表示日期,没有时间或时区。要确定诸如“今天”之类的日期,您需要一个时区(ZoneId)。例如,巴黎的新日早些时候比蒙特利尔早。 如果您需要仅限日期值,建议您在此类类别中添加成员。

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );

日期 - 时间

如果您想要日期时间,请首先考虑Instant课程。这标志着UTC时间轴上的一个时刻。几乎总是最好用UTC进行业务逻辑和数据存储。 当您需要特定时刻而非模糊日期时,请将此类型的成员添加到您的班级。

Instant now = Instant.now();

要在期望/预期时区内向用户显示,请将时区应用于即时消息以获取ZonedDateTime

ZonedDateTime zdt = ZonedDateTime.ofInstant( now , ZoneId.of( "America/Montreal" ) );

当天的第一时刻

我不推荐这种策略,而是直接回答你的问题,关于检测日期时间值的时间是否恰好是一天中的第一时刻...

首先你需要考虑时区。上面提到的所有这些日期时间类都以UTC中的count-from - epoch跟踪时间。旧类以毫秒为单位,新的以纳秒为单位。新旧时代是UTC 1970年的第一个时刻。因此,当您在问题中提出时,没有没有时间的日期时间。最接近的是日期时间,其时间恰好是一天中的第一时刻。似乎是你的情况(尽管我上面的讨论强烈建议你改变你的情况)。

如何确定日期时间是否包含当天的第一时刻?首先,你必须考虑时区。你想要UTC或你想要一个特定的时区,如America/Montreal。取决于您的业务规则。

如果以java.util.Date开头,请先转换为java.time。

Instant instant = myJUDate.toInstant();

请注意,日期总是00:00:00.0开始。由于夏令时(DST)以及可能的其他异常,在某些地方,日期的第一个时刻是不同的wall-clock time。 java.time框架可以使用LocalDate类及其atStartOfDay方法确定当天的第一时刻。

因此,在确定我们关心的时区后,我们将Instant调整为ZonedTimeZone。

Instant instant = Instant.now ();
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );

接下来我们需要看看那是否是当天的第一时刻。所以我们转换为LocalDate,然后通过调用atStartOfDay返回到另一个ZonedDateTime。将第一个ZonedDateTime与第二个ZonedDateTime进行比较,告诉我们原始版本是否确实在当天的开始。总结一下:我们正在转换 ZonedDateTime→LocalDate→ZonedDateTime

// Convert to LocalDate, to get start of day, to compare to above.
LocalDate localDate = zdt.toLocalDate ();
ZonedDateTime startOfDay = localDate.atStartOfDay ( zoneId );
Boolean isStartOfDay = ( zdt.isEqual ( startOfDay ) );

转储到控制台。

System.out.println ( "instant: " + instant + " for zoneId: " + zoneId + " is zdt: " + zdt + " if compared to startOfDay: " + startOfDay + " is T/F: " + isStartOfDay );
  

即时:2015-12-12T23:20:23.560Z for zoneId:America / Montreal is zdt:2015-12-12T18:20:23.560-05:00 [America / Montreal]如果与startOfDay相比:2015-12 -12T00:00-05:00 [America / Montreal]是T / F:false

如果您想要UTC而不是特定时区,请在上面的代码中使用常量ZoneOffset.UTC作为ZoneId对象。 ZoneOffsetZoneId的子类。

答案 2 :(得分:1)

假设您正在使用从java.util.Date派生的java.sql.Date,则Date对象不可能没有时间值。 请注意文档: http://docs.oracle.com/javase/7/docs/api/java/sql/Date.html Date对象实例保存一个毫秒值,准确地说是当前时间与UTC时间1970年1月1日午夜之间的差异(以毫秒为单位)。

答案 3 :(得分:0)

使用Calendar对象。日历可以为您提供Date值的所有字段的结构化访问权限,即年,月,日,小时,分钟,秒等。这将允许您检查时间字段是否为非零。正如JB Nizet所说,时间部分可能恰好为零,在这种情况下,你会将它误解为只有日期的值。