2009-05-31 2 views
5

С данной даты мне нужно рассчитать полночь своего дня. Вот что я придумал. Это так уродливо, что я считаю, что должен быть лучший способ.Расчет дня с датой

private Date day(Date creation) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.setTime(creation); 
    calendar.set(Calendar.HOUR_OF_DAY, 0); 
    calendar.set(Calendar.MINUTE, 0); 
    calendar.set(Calendar.SECOND, 0); 
    calendar.set(Calendar.MILLISECOND, 0); 
    return calendar.getTime(); 
} 

Предложения?

Kent

+3

господи - первый Алан Кей, теперь Кент Бек. SO - это место, которое должно быть ... – duffymo

+0

Хуже того, код, который вы отправили, не учитывает часовой пояс, который вам может или не нужно. – Yishai

+0

прост проверить это [здесь] (http://developer-dot-android.blogspot.com/2012/03/date-into-day-tutorial.html) –

ответ

7

Вы должны рассмотреть встроенный API-интерфейс даты. Вместо этого используйте API даты и времени Joda.

Замена замены вашего метода.

private Date day(Date creation) { 
    return new DateMidnight(creation).toDate(); 
} 

Вот простой тест:

public static void main(String[] args) { 
    final Date creation = new Date(); 
    final Date midnight = new Foobar().day(creation); 
    System.out.println("creation = " + creation); 
    System.out.println("midnight = " + midnight); 
} 

Выход:

creation = Sun May 31 10:09:38 CEST 2009  
midnight = Sun May 31 00:00:00 CEST 2009 
2

Если вы ищете по местному времени, что это лучшее, что вы собираетесь получить. И хотя вы можете считать это уродливым, есть (потенциально) много происходит за кулисами.

Если вы хотите полночь UTC, следующий будет работать:

public static void main(String[] argv) 
throws Exception 
{ 
    final long MILLIS_PER_DAY = 24 * 3600 * 1000L; 

    long midnightUTC = (System.currentTimeMillis()/MILLIS_PER_DAY) * MILLIS_PER_DAY; 
} 

Edit: Я действительно не рекомендую использовать местные даты в «производства» кода. Они вызывают больше проблем, чем их стоит, - считают человека на западном побережье США, который внезапно находит свой «день», урезанный на 3 часа, потому что у компьютера на восточном побережье есть другая идея полуночи.

5

JODA может иметь лучшее решение за счет другой зависимости от библиотеки. Я смотрю его DateMidnight property. Мне жаль, что я не могу ответить более авторитетно, но я сам не являюсь пользователем JODA.

0

Я думаю, что единственный способ, которым вы собираетесь сделать этот код значительно лучше, - это изменение представления. Например,

  • Представляют день по системе «абсолютная дата» объясняется Нахум Дершовицем и Эд Рейнгольд в Calendrical Calculations.

  • Представьте время, считая секунды с полуночи. Или, если вам требуется суб-второе разрешение, считайте миллисекунды.

Из вашего краткого примера я не могу сказать, в каких точках в вашей программе, вы должны быть совместимы с существующими Date и Calendar классов, или если вы можете создать полезный подкласс, используя Санер представление.

0

Не запрограммировал Java через некоторое время, но вы могли бы назвать это set method, передавая текущие значения для года, месяца и дня. Хотя, читая немного близко, вам, возможно, придется сначала позвонить по-русски. Это может быть или не быть менее подробным, чем использование вашего текущего метода.

1

JODA это путь, если у вас есть серьезные потребности в календаре, по крайней мере, пока JSR-310 не попадает в JDK (возможно 1.7, если не 1.8).

Это, как говорится, есть несколько вещей, которые можно сделать, чтобы сделать этот код немного приятнее.

Это не принесет никаких наград за производительность. Вы можете сделать стандарт для цикла, полагаясь на конкретные значения полей (класс Calendar имеет поле FIELD_COUNT, подразумевающее, что вы можете сделать что-то подобное), но это может вызвать проблемы при реализации JDK и между версиями.

0

Это только дополнение к первоначально размещенному коду. Он устанавливает год, месяц и день в новом объекте GregorianCalendar вместо того, чтобы очищать все, кроме Года, Месяца и Дня, в переменной календаря. Это не очень улучшилось, но я думаю, что яснее сказать, какие поля вы копируете, а не какие поля вы игнорируете.

public Date day(Date creation) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.setTime(creation); 
    return new GregorianCalendar(
      calendar.get(Calendar.YEAR), 
      calendar.get(Calendar.MONTH), 
      calendar.get(Calendar.DAY_OF_MONTH)).getTime(); 
} 

Лично я думаю, что я поеду с библиотекой Джода, предложенной другими.

1

Использование date4j библиотеки:

DateTime start = dt.getStartOfDay();