将时间设置为00:00:00


121

我在用Java重置小时数时遇到问题。对于给定的日期,我要将小时设置为00:00:00。

这是我的代码:

/**
     * Resets milliseconds, seconds, minutes and hours from the provided date
     *
     * @param date
     * @return
     */
    public static Date trim(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR, 0);

        return calendar.getTime();
    }

问题是,时间有时是这样12:00:00,有时是这样00:00:00,当我查询数据库中保存的实体以及查询07.02.2013 00:00:00的实际实体时间即存储12:00:00失败时。

我知道12:00:00 == 00:00:00

我正在使用AppEngine。这是Appengine错误,问题还是其他问题?还是取决于其他因素?


这可能与不同的语言环境有关吗,还是总是在同一台PC上发生?
LostBoy

当我在appengine上部署时会发生这种情况。
Adelin

许多其他用于缩短时间的解决方案:stackoverflow.com/a/1908955/2646526
heenenee,2016年

仅供参考,麻烦的旧日期,时间类,如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat现在的遗产,由取代java.time内置到Java 8的Java 9.请参见类由Oracle教程
罗勒·布尔克

1
我使用calendar.set(Calendar.HOUR_OF_DAY, 0);,以达到我的目的,效果很好。
hariprasad

Answers:


209

使用另一个常数代替Calendar.HOUR,使用Calendar.HOUR_OF_DAY

calendar.set(Calendar.HOUR_OF_DAY, 0);

Calendar.HOUR 使用0-11(用于AM / PM),并且 Calendar.HOUR_OF_DAY使用0-23。

引用Javadocs:

公共静态最终int HOUR

get和set的字段编号,指示上午或下午的时间。HOUR用于12小时制(0-11)。中午和午夜用0而不是12表示。例如,在10:04:15.250 PM,小时是10。

公共静态最终int HOUR_OF_DAY

get和set的字段号指示一天中的小时。HOUR_OF_DAY用于24小时制。例如,在10:04:15.250 PM,HOUR_OF_DAY是22。

测试(“现在”目前是2013年7月23日太平洋夏令时间的14:55):

public class Main
{
   static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args)
    {
        Calendar now = Calendar.getInstance();
        now.set(Calendar.HOUR, 0);
        now.set(Calendar.MINUTE, 0);
        now.set(Calendar.SECOND, 0);
        System.out.println(sdf.format(now.getTime()));
        now.set(Calendar.HOUR_OF_DAY, 0);
        System.out.println(sdf.format(now.getTime()));
    }
}

输出:

$ javac Main.java
$ java Main
2013-07-23 12:00:00
2013-07-23 00:00:00

3
@JarrodRoberson但是使用Calendar.HOUR不会将PM设置为AM,而是将其设置为中午12:00。
rgettman

您能帮我建立小时,分钟和秒的LocalDate吗?我知道一种选择是遵循DateTime。
伍迪2015年

11
谁创建了“ HOUR”和“ HOUR_OF_DAY”字段,谁都应该弄乱并配给定量。
AndroidDev 2015年

1
@AndroidDev谁发明了am / pm谁都应该得到相同的结果...这也适用于非度量标准

1
仅供参考,麻烦的旧日期,时间类,如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat现在的遗产,由取代java.time内置到Java 8的Java 9.请参见类由Oracle教程
罗勒·布尔克

29

java.time

使用java.timeJava 8和更高版本中内置的框架。请参阅教程

import java.time.LocalTime;
import java.time.LocalDateTime;

LocalDateTime now = LocalDateTime.now(); # 2015-11-19T19:42:19.224
# start of a day
now.with(LocalTime.MIN); # 2015-11-19T00:00
now.with(LocalTime.MIDNIGHT); # 2015-11-19T00:00

如果您不需要一天中的时间(小时,分钟,秒等部分),请考虑使用LocalDate课堂。

LocalDate.now(); # 2015-11-19

自从首次提出此问题以来,Java 1.8已经发布,这应该是新的接受的答案。
matt forsythe

LocalDateTime正是为此使用了错误的类。由于它缺少时区或从UTC偏移的任何概念,因此无法表示一个时刻。打电话LocalDateTime.now几乎是没有道理的。使用ZonedDateTime代替。否则,您将忽略关键的时区问题。一方面,某些区域中的某些日期不是从00:00开始!
罗勒·布尔克

12

这是我用来执行此操作的几个实用程序功能。

/**
 * sets all the time related fields to ZERO!
 *
 * @param date
 *
 * @return Date with hours, minutes, seconds and ms set to ZERO!
 */
public static Date zeroTime( final Date date )
{
    return DateTimeUtil.setTime( date, 0, 0, 0, 0 );
}

/**
 * Set the time of the given Date
 *
 * @param date
 * @param hourOfDay
 * @param minute
 * @param second
 * @param ms
 *
 * @return new instance of java.util.Date with the time set
 */
public static Date setTime( final Date date, final int hourOfDay, final int minute, final int second, final int ms )
{
    final GregorianCalendar gc = new GregorianCalendar();
    gc.setTime( date );
    gc.set( Calendar.HOUR_OF_DAY, hourOfDay );
    gc.set( Calendar.MINUTE, minute );
    gc.set( Calendar.SECOND, second );
    gc.set( Calendar.MILLISECOND, ms );
    return gc.getTime();
}

6

JAVA 8的另一种方式:

LocalDateTime localDateTime = LocalDateTime.now().truncatedTo(ChronoUnit.HOURS);

但是,编辑已经存在的日期会更加有用。


1
LocalDateTime无法代表一个时刻,因为它缺少时区或UTC偏移量的概念。打电话LocalDateTime.now几乎没有任何意义。您应该ZonedDateTime改为使用。
罗勒·布尔克

3

您最好主要将时区设置为DateFormat组件,如下所示:

DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));

然后,您可以通过将0毫秒传递给格式化程序来获得“ 00:00:00”的时间:

String time = dateFormat.format(0);

或者您可以创建Date对象:

Date date = new Date(0); // also pass milliseconds
String time = dateFormat.foramt(date);

或者您可以使用日历组件拥有更多的可能性,但还应该将日历实例的时区设置为GMT:

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.US);
calendar.set(Calendar.HOUR_OF_DAY, 5);
calendar.set(Calendar.MINUTE, 37);
calendar.set(Calendar.SECOND, 27);

dateFormat.format(calendar.getTime());

2

tl; dr

myJavaUtilDate                                 // The terrible `java.util.Date` class is now legacy. Use *java.time* instead.
.toInstant()                                   // Convert this moment in UTC from the legacy class `Date` to the modern class `Instant`.
.atZone( ZoneId.of( "Africa/Tunis" ) )         // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone).
.toLocalDate()                                 // Extract the date-only portion.
.atStartOfDay( ZoneId.of( "Africa/Tunis" ) )   // Determine the first moment of that date in that zone. The day does *not* always start at 00:00:00.

java.time

您使用的是可怕的旧日期时间类,而该类早已被JSR 310中定义的现代java.time类所取代。

DateInstant

A java.util.Date代表UTC的时刻。其替换为Instant。调用添加到旧类中的新转换方法。

Instant instant = myJavaUtilDate.toInstant() ;

时区

指定您希望新的时间有意义的时区。

指定适当的时区名称,格式Continent/Region,如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4字母的缩写,例如EST或,IST因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;

ZonedDateTime

应用ZoneIdInstant获得ZonedDateTime。时间轴上的相同时刻,相同点,但挂钟时间不同。

ZonedDateTime zdt = instant.atZone( z ) ;

改变时间

您要求更改时间。应用a LocalTime更改所有时间部分:小时,分钟,秒和小数秒。ZonedDateTime实例化一个新的,其值基于原始值。该java.time类使用这种不可变对象模式来提供线程安全

LocalTime lt = LocalTime.of( 15 , 30 ) ;  // 3:30 PM.
ZonedDateTime zdtAtThreeThirty = zdt.with( lt ) ; 

一天的第一刻

但是您专门要求00:00。因此,显然您想要一天的第一刻。当心:某些地区的某些日子并非从00:00:00开始。由于诸如夏令时(DST)之类的异常,它们可能在其他时间(例如01:00:00)开始。

java.time确定第一时刻。提取仅日期部分。然后通过时区以获得第一时间。

LocalDate ld = zdt.toLocalDate() ;
ZonedDateTime zdtFirstMomentOfDay = ld.atStartOfDay( z ) ;

适应UTC

如果您需要返回UTC,请提取一个Instant

Instant instant = zdtFirstMomentOfDay.toInstant() ;

InstantDate

如果需要java.util.Date与尚未更新为java.time的旧代码进行互操作,请转换。

java.util.Date d = java.util.Date.from( instant ) ;

1

这样做可能会更容易(在Java 8中)

LocalTime.ofNanoOfDay(0)

谢谢,我在过去的两年中和其他的Java 6/7一起工作过。我现在回到Java(在Groovy上做了一些工作之后),并且喜欢Java 8的不同之处。
meszias

1

我们可以使用Java 8 / Joda-datetime api的 LocalDate类将java.util.Date时间部分设置为00:00:00

Date datewithTime = new Date() ; // ex: Sat Apr 21 01:30:44 IST 2018
LocalDate localDate = LocalDate.fromDateFields(datewithTime);
Date datewithoutTime = localDate.toDate(); // Sat Apr 21 00:00:00 IST 2018

1

如果需要字符串格式00:00:00,则应使用SimpleDateFormat,如下所示。使用“ H”代替“ h”。

Date today = new Date();
SimpleDateFormat ft = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); 
//not SimpleDateFormat("dd-MM-yyyy hh:mm:ss")
Calendar calendarDM = Calendar.getInstance();
calendarDM.setTime(today);
calendarDM.set(Calendar.HOUR, 0);
calendarDM.set(Calendar.MINUTE, 0);
calendarDM.set(Calendar.SECOND, 0);
System.out.println("Current Date: " + ft.format(calendarDM.getTime()));

//Result is: Current Date: 29-10-2018 00:00:00

0

执行此操作的另一种方法是使用DateFormat而无需花费任何时间:

public static Date trim(Date date) {
    DateFormat format = new SimpleDateFormat("dd.MM.yyyy");
    Date trimmed = null;
    try {
        trimmed = format.parse(format.format(date));
    } catch (ParseException e) {} // will never happen
    return trimmed;
}


0

随着Java8添加新的Date函数,我们可以轻松地做到这一点。


    // If you have instant, then:
    Instant instant1 = Instant.now();
    Instant day1 = instant1.truncatedTo(ChronoUnit.DAYS);
    System.out.println(day1); //2019-01-14T00:00:00Z

    // If you have Date, then:
    Date date = new Date();
    Instant instant2 = date.toInstant();
    Instant day2 = instant2.truncatedTo(ChronoUnit.DAYS);
    System.out.println(day2); //2019-01-14T00:00:00Z

    // If you have LocalDateTime, then:
    LocalDateTime dateTime = LocalDateTime.now();
    LocalDateTime day3 = dateTime.truncatedTo(ChronoUnit.DAYS);
    System.out.println(day3); //2019-01-14T00:00
    String format = day3.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    System.out.println(format);//2019-01-14T00:00:00


LocalDateTime无法代表一个时刻,因为它缺少时区或UTC偏移量的概念。打电话LocalDateTime.now几乎没有任何意义。您应该ZonedDateTime改为使用。
罗勒·布尔克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.