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
How to trim minutes and hours and seconds from Date object?
提问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:
更直接地解决这个问题:
- Convert to java.time, from
java.util.Datetojava.time.Instant. - Truncate to the date.
- 转换为 java.time,从
java.util.Date到java.time.Instant. - 截断到日期。
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.Date并Instant表示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 类?
- Java SE 8and SE 9and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- The ThreeTenABPproject adapts ThreeTen-Backport(mentioned above) for Android specifically.
- See How to use….
- Java SE 8和SE 9及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6和SE 7
- 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植。
- 安卓
- 所述ThreeTenABP项目适应ThreeTen-反向移植(上述)为Android特异性。
- 请参阅如何使用......。
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 的试验场。你可能在这里找到一些有用的类,比如Interval,YearWeek,YearQuarter,和更多。
回答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;
}

