Как обрезать минуты, часы и секунды от объекта Date?
мне нужно сделать карту, где нужные ключи. 2 объекты date равны, если они имеют одинаковое значение getTime()
метод.
меня интересует только год, месяц и день. Как я могу!--1--> ненужные часы и минуты, чтобы получить "чистый" даты?
6 ответов
используйте пользовательский 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);
о java.util.Date
отстой, используйте время Joda и т. д.
вы можете создать 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();
}
и использовать его как:
map.put( trim( aDate ), xyz() );
...
map.get( trim( otherDate ));
вот полный рабочий пример:
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();
}
}
выход:
$ java DateTest
equals? = false, hashCode? = false
equals? = true, hashCode? = true
long time1 = myDate1.getTime()/(1000*60*60*24);
long time2 = myDate2.getTime()/(1000*60*60*24);
if (time1 == time2)
// equal!
это подталкивает незначительные значения ниже десятичного, затем целочисленное деление усекает его, поэтому остаются только значения, значимые на уровне дня и выше.
Если вы хотите сделать эти даты снова, просто примените смещение обратно к усеченным значениям:
myDate1.setTime(time1 * (1000*60*60*24));
myDate2.setTime(time2 * (1000*60*60*24));
tl; dr
LocalDate ld =
myUtilDate.toInstant()
.atZone( ZoneId.of( "America/Montreal" ) )
.toLocalDate();
подробности
в вопросе и других ответах используются устаревшие старые классы даты-времени, которые оказались плохо спроектированными, запутанными и хлопотными. Теперь наследие, вытесненное java.классы время.
Instant
усе
чтобы более непосредственно обратиться к вопросу:
- преобразовать в java.время, от
java.util.Date
tojava.time.Instant
. - усечь в дата.
преобразование с помощью новых методов, добавленных к старым классам.
Instant instant = myUtilDate.toInstant();
функция усечения встроена в Instant
класса. The Instant
класс представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) цифр десятичной дробью).
Instant instantTruncated = instant.truncatedTo( ChronoUnit.DAYS );
ZonedDateTime
& LocalDate
но подход выше имеет проблемы. Оба!--5--> и Instant
представляют момент на временной шкале в формате UTC, а не в определенном часовом поясе. Поэтому, если вы отбросите время суток или установите его в 00:00:00
, вы получаете дату, которая имеет смысл только в UTC. Если вы имели в виду дату Окленд NZ или Монреаль Квебек, вы можете иметь неправильную дату.
таким образом, лучший подход заключается в применении желаемого / ожидаемого часового пояса к Instant
и ZonedDateTime
.
другая проблема заключается в том, что мы неправильно используем объект date-time для представлять значение только для даты. Вместо этого мы должны использовать класс только для свиданий. От ZonedDateTime
мы должны извлечь LocalDate
если все, что вы хотите, это только дата.
на LocalDate
класс представляет значение только даты без времени суток и без часового пояса.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
LocalDate ld = zdt.toLocalDate();
о java.время
на java.время framework встроен в Java 8 и более поздние версии. Эти классы вытесняют беспокойных старых наследие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
на Joda Времени, теперь режим обслуживания, советует миграцию на java.время.
чтобы узнать больше, см. В Oracle Учебник. И search Stack Overflow для многих примеров и объяснений. Спецификация JSR 310.
где получить java.время занятий?
-
Java SE 8 и SE 9 и позже
- встроенный.
- часть стандартного API Java со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
-
Java SE 6 и SE 7
- большая часть java.функциональность времени портированы с Java 6 и 7 в ThreeTen-Backport.
-
Android
- на ThreeTenABP проект приспосабливается ThreeTen-Backport (упомянуто выше) для Android конкретно.
- посмотреть как использовать....
на ThreeTen-Extra проект расширяет java.время с дополнительными занятиями. Этот проект является испытательной площадкой для возможных будущих дополнений к java.время. Здесь вы можете найти полезные классы, такие как Interval
, YearWeek
, YearQuarter
и больше.
преобразовать свой Date
объекты должны быть равны, если имеют один и тот же год, месяц и день:
public static Date convertDate(Date oldDate) {
final long oneDay = 1000 * 60 * 60 * 24;
long newDate = oldDate.getTime() / oneDay;
return new Date( newDate * oneDay );
}
предлагаемое решение не работает в Android, поскольку оно застряло на Java 7, и поэтому календарь глючит. Другие решения также имели ошибки, потому что они не учитывали смещение часового пояса или имели проблемы с переполнением int, прежде чем они будут преобразованы в long.
Это решение, кажется, работает:
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;
}