【问题标题】:Set time to 00:00:00将时间设置为 00:00:00
【发布时间】:2013-07-23 04:42:53
【问题描述】:

我在 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 上的实体时,实际存储的实体时间是@987654331 @查询失败。

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

我正在使用 AppEngine。这是 appengine 错误、问题还是其他问题?还是依赖于别的东西?

【问题讨论】:

  • 这可能与不同的语言环境有关,还是一直在同一台 PC 上发生?
  • 当我在 appengine 上部署时会发生这种情况。
  • 很多其他的切断时间的解决方案:stackoverflow.com/a/1908955/2646526
  • 仅供参考,麻烦的旧日期时间类,例如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被 Java 8 和 Java 中内置的 java.time 类所取代9. 见Tutorial by Oracle
  • 我使用了calendar.set(Calendar.HOUR_OF_DAY, 0);,就我的目的而言,效果很好。

标签: java java.util.calendar


【解决方案1】:

使用另一个常量代替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:

public static final int HOUR

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

public static final int HOUR_OF_DAY

get 和 set 的字段编号 表示一天中的小时。 HOUR_OF_DAY 用于 24 小时 钟。例如,在晚上 10:04:15.250,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

【讨论】:

  • @JarrodRoberson 但是使用 Calendar.HOUR 不会将 PM 设置为 AM,而是将其保留为中午 12:00。
  • 创建 HOUR 和 HOUR_OF_DAY 字段的人应该被鞭打并配给口粮。
  • @AndroidDev 发明了 am/pm 的人应该得到同样的待遇......这也适用于非公制标准
  • 仅供参考,麻烦的旧日期时间类,如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被 Java 8 和 Java 中内置的 java.time 类所取代9. 见Tutorial by Oracle
  • 一切都正确,但也应该有millis:now.set(Calendar.MILLISECOND, 0);
【解决方案2】:

java.time

使用 Java 8 及更高版本中内置的 java.time 框架。见Tutorial

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 发布以来新接受的答案。
  • LocalDateTime 正是用于此的错误的类。它不能代表一个时刻,因为它缺乏任何时区或与 UTC 偏移的概念。打电话给LocalDateTime.now 几乎没有意义。请改用ZonedDateTime。否则,您将忽略关键的时区问题。一方面,某些区域的某些日期从 00:00 开始!
【解决方案3】:

这里有几个我用来做这个的实用函数。

/**
 * 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();
}

【讨论】:

    【解决方案4】:

    另一种 JAVA 8 方式:

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

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

    【讨论】:

    • LocalDateTime 不能代表时刻,因为它缺少任何时区或与 UTC 偏移的概念。打电话给LocalDateTime.now 几乎没有意义。您应该改用ZonedDateTime
    【解决方案5】:

    您最好将时区主要设置为 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());
    

    【讨论】:

      【解决方案6】:

      tl;博士

      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

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

      Instant instant = myJavaUtilDate.toInstant() ;
      

      时区

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

      Continent/Region 的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 2-4 字母缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

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

      ZonedDateTime

      ZoneId 应用于Instant 以获得ZonedDateTime。同一时刻,时间轴上的同一点,但挂钟时间不同。

      ZonedDateTime zdt = instant.atZone( z ) ;
      

      改变时间

      您要求更改时间。应用LocalTime 更改所有时间部分:小时、分钟、秒、小数秒。实例化一个新的ZonedDateTime,其值基于原始值。 java.time 类使用这个immutable objects 模式来提供thread-safety

      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 ) ;
      

      【讨论】:

        【解决方案7】:

        随着 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
        【解决方案8】:

        见以下代码:

            String datePattern24Hrs = "yyyy-MM-dd HH:mm:ss";
            String datePattern12Hrs = "yyyy-MM-dd hh:mm:ss";
        
            SimpleDateFormat simpleDateFormat24Hrs = new SimpleDateFormat(datePattern24Hrs);
            SimpleDateFormat simpleDateFormat12Hrs = new SimpleDateFormat(datePattern12Hrs);
        
            Date dateNow = new Date();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(dateNow);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            Date dateTime = calendar.getTime();
        
            String dateTimeIn24Hrs = simpleDateFormat24Hrs.format(dateTime);
            String dateTimeIn12Hrs = simpleDateFormat12Hrs.format(dateTime);
        
            System.out.println("DateTime in 24Hrs: ".concat(dateTimeIn24Hrs));
            System.out.println("DateTime in 12Hrs: ".concat(dateTimeIn12Hrs));
        

        预期输出如下:

        • 24小时内的日期时间:2021-06-29 00:00:00
        • DateTime in 12Hrs: 2021-06-29 12:00:00

        我希望它对您正在寻找的答案有所帮助。

        【讨论】:

          【解决方案9】:

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

          LocalTime.ofNanoOfDay(0)
          

          【讨论】:

          • 谢谢,我在过去 2 年中使用过其他东西,以及之前的 Java 6/7。我现在回到了 Java(在 Groovy 上做了一些事情之后)并且喜欢 Java 8 的不同之处。
          【解决方案10】:

          另一种简单的方法,

          final Calendar today = Calendar.getInstance();
                  today.setTime(new Date());
                  today.clear(Calendar.HOUR_OF_DAY);
                  today.clear(Calendar.HOUR);
                  today.clear(Calendar.MINUTE);
                  today.clear(Calendar.SECOND);
                  today.clear(Calendar.MILLISECOND);
          

          【讨论】:

            【解决方案11】:

            另一种方法是使用 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;
            }
            

            【讨论】:

              【解决方案12】:

              您可以通过以下方式做到这一点:

              Calendar cal = Calendar.getInstance();
              cal.set(year, month, dayOfMonth, 0, 0, 0);
              Date date = cal.getTime();
              

              【讨论】:

                【解决方案13】:

                如果您需要字符串格式 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
                

                【讨论】:

                  【解决方案14】:

                  在 Java 8 之前:

                  Calendar calendar = Calendar.getInstance();
                  calendar.setTime(new Date());
                  calendar.set(Calendar.HOUR, 0);
                  calendar.set(Calendar.MINUTE, 0);
                  calendar.set(Calendar.SECOND, 0);
                  

                  Java 8 之后:

                  LocalDateTime.now().with(LocalTime.of(0, 0, 0))
                  

                  【讨论】:

                    【解决方案15】:

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

                    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
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多