java 如何从 Date 对象中修剪分钟、小时和秒?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2775411/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 22:46:22  来源:igfitidea点击:

How to trim minutes and hours and seconds from Date object?

javadate

提问by Roman

I need to make map where Dates are keys. 2 date objects are equals if they have the same value of getTime()method.

我需要制作地图,其中日期是关键。如果两个日期对象具有相同的getTime()方法值,则它们相等。

I'm interested only in year, month and day. How can I trimunnecessary hours and minutes to get 'clear' dates?

我只对年、月和日感兴趣。我怎样才能trim不必要的小时和分钟来获得“明确”的日期?

采纳答案by polygenelubricants

Use a custom Comparator<Date>for a TreeMap<Date,V>.

使用自定义Comparator<Date>TreeMap<Date,V>

    Comparator<Date> ymdComparator = new Comparator<Date>() {
        @Override public int compare(Date d1, Date d2) {
            return 
                d1.getYear() < d2.getYear() ? -1 :
                d1.getYear() > d2.getYear() ? +1 :
                d1.getMonth() < d2.getMonth() ? -1 :
                d1.getMonth() > d2.getMonth() ? +1 :
                d1.getDay() < d2.getDay() ? -1 :
                d1.getDay() > d2.getDay() ? +1 :
                0;
        }
    };

    SortedMap<Date,V> map = new TreeMap<Date,V>(ymdComparator);

Oh, java.util.Datesucks, use Joda Time, etc.

哦,java.util.Date糟透了,使用 Joda Time 等。

回答by OscarRyz

You can create a trimmethod:

您可以创建一个trim方法:

public static Date trim(Date date) {
      Calendar cal = Calendar.getInstance();
      cal.clear(); // as per BalusC comment.
      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();
 }

And use it like:

并像这样使用它:

 map.put( trim( aDate ), xyz() );

...

...

 map.get( trim( otherDate ));

Here's a complete working sample:

这是一个完整的工作示例:

import java.util.Calendar;
import java.util.Date;
import static java.util.Calendar.*;
import static java.lang.System.out;


public class DateTest {
    public static void main( String [] args )  throws InterruptedException {
            Date date = new Date();
            Thread.sleep(1);
            Date other = new Date();
            out.printf("equals? = %s, hashCode? = %s %n", (date.equals(other)), (date.hashCode() == other.hashCode()));

            Date todayeOne = trim( date );
            Date todayTwo  = trim( date );


            out.printf("equals? = %s, hashCode? = %s %n", (todayeOne.equals(todayTwo)), (todayeOne.hashCode() == todayTwo.hashCode()));

    }

    public static Date trim(Date date) {
          Calendar cal = Calendar.getInstance();
          cal.setTime( date );
          cal.set(HOUR_OF_DAY, 0);
          cal.set(MINUTE, 0);
          cal.set(SECOND, 0);
          cal.set(MILLISECOND, 0);
          return cal.getTime();
     }

}

output:

输出:

$ java DateTest 
equals? = false, hashCode? = false 
equals? = true, hashCode? = true 

回答by Basil Bourque

tl;dr

tl;博士

LocalDate ld =
    myUtilDate.toInstant()
              .atZone( ZoneId.of( "America/Montreal" ) )
              .toLocalDate();

Details

细节

The Question and other Answers use outmoded old date-time classes that have proven to be poorly-designed, confusing, and troublesome. Now legacy, supplanted by the java.time classes.

问题和其他答案使用过时的旧日期时间类,这些类已被证明设计不良、混乱且麻烦。现在是遗留的,被 java.time 类取代。

Instanttruncated

Instant被截断的

To more directly address the question:

更直接地解决这个问题:

  1. Convert to java.time, from java.util.Dateto java.time.Instant.
  2. Truncate to the date.
  1. 转换为 java.time,从java.util.Datejava.time.Instant.
  2. 截断到日期。

Convert via new methods added to the old classes.

通过添加到旧类的新方法进行转换。

Instant instant = myUtilDate.toInstant();

The truncation feature is built into the Instantclass. The Instantclass represents a moment on the timeline in UTCwith a resolution of nanoseconds(up to nine (9) digits of a decimal fraction).

截断功能内置于Instant类中。该Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多小数的9个位数)。

Instant instantTruncated = instant.truncatedTo( ChronoUnit.DAYS );

ZonedDateTime& LocalDate

ZonedDateTime& LocalDate

But the approach above has issues. Both java.util.Dateand Instantrepresent a moment on the timeline in UTC rather than an particular time zone. So if you drop the time-of-day, or set it to 00:00:00, you are getting a date that only makes sense in UTC. If you meant the date for Auckland NZ or Montréal Québec, you may have the wrong date.

但是上面的方法有问题。双方java.util.DateInstant表示UTC时间线,而不是一个特定的时间段上一会儿。因此,如果您删除一天中的时间,或将其设置为00:00:00,您将获得一个仅在 UTC 中有意义的日期。如果您指的是新西兰奥克兰或魁北克省的日期,那么您的日期可能有误。

So a better approach is to apply your desired/expected time zone to the Instantto get a ZonedDateTime.

所以,更好的方法是到你想要的/预期的时区适用于Instant获得ZonedDateTime

Another problem is that we are inappropriately using a date-time object to represent a date-only value. Instead we should use a date-only class. From the ZonedDateTimewe should extract a LocalDateif all you want is the date-only.

另一个问题是我们不恰当地使用日期时间对象来表示仅日期值。相反,我们应该使用仅限日期的类。如果您想要的只是日期,ZonedDateTime我们应该从中提取一个LocalDate

The LocalDateclass represents a date-only value without time-of-day and without time zone.

LocalDate级表示没有时间一天和不同时区的日期,唯一的价值。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
LocalDate ld = zdt.toLocalDate();


About java.time

关于 java.time

The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

The Joda-Timeproject, now in maintenance mode, advises migration to java.time.

现在处于维护模式Joda-Time项目建议迁移到 java.time。

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多

回答by Ipsquiggle

long time1 = myDate1.getTime()/(1000*60*60*24);
long time2 = myDate2.getTime()/(1000*60*60*24);
if (time1 == time2)
    // equal!

This pushes insignificant values below the decimal, then integer division truncates it, so only values significant at the Day level and higher are left.

这会将不重要的值推到小数点以下,然后整数除法将其截断,因此只剩下在 Day 级别和更高级别重要的值。

If you want to make those dates again, just apply the offset back to the truncated values:

如果您想再次创建这些日期,只需将偏移量应用回截断的值:

myDate1.setTime(time1 * (1000*60*60*24));
myDate2.setTime(time2 * (1000*60*60*24));

回答by ablaeul

Just convert your Dateobjects to be equal, if the have the same year, month and day:

只需将您的Date对象转换为相等,如果它们具有相同的年、月和日:

public static Date convertDate(Date oldDate) {
    final long oneDay = 1000 * 60 * 60 * 24;
    long newDate = oldDate.getTime() / oneDay;
    return new Date( newDate * oneDay );
}

回答by Carlos Hoyos

Proposed solution does not work in Android as it is stuck on Java 7 and so Calendar is buggy. Others solutions also had bugs because they did not take into account TimeZone offset, or have problems with int overflow before they get converted to long.

提议的解决方案在 Android 中不起作用,因为它停留在 Java 7 上,因此日历有问题。其他解决方案也有错误,因为他们没有考虑 TimeZone 偏移,或者在转换为 long 之前存在 int 溢出问题。

This solution seems to work:

这个解决方案似乎有效:

public static final long MILLISECONDS_PER_DAY=(1000L * 60L * 60L * 24L);

public static long convertDate(Date d) {
    TimeZone tz = TimeZone.getDefault();
    long val = d.getTime() + tz.getOffset(d.getTime()); /*local timezone offset in ms*/
    return val / MILLISECONDS_PER_DAY;
}

public static Date convertDate(long date) {
    TimeZone tz = TimeZone.getDefault();
    Date d=new Date();
    d.setTime(date*MILLISECONDS_PER_DAY-tz.getOffset(d.getTime()));
    return d;
}