Как получить дату без времени в Java?

Продолжение с вопроса Java-программа для получения текущей даты без отметки времени:

Каков наиболее эффективный способ получить объект Date без времени? Есть ли другой способ, чем эти два?

// Method 1
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dateWithoutTime = sdf.parse(sdf.format(new Date()));

// Method 2
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
dateWithoutTime = cal.getTime();

Обновление

  • Я знал о Joda-Time; Я просто пытаюсь избежать дополнительной библиотеки для такой простой (я думаю) задачи. Но на основе ответов до сих пор Joda-Time кажется чрезвычайно популярным, поэтому я мог бы рассмотреть его.

  • Эффективным я имею в виду, что я хочу избежать создания временного объекта String, используемого method 1, между тем method 2 кажется взломом вместо решения.

Ответ 1

Вам нужно использовать java.util.Date? Я бы рекомендовал вам использовать Joda Time или пакет java.time от Java 8. В частности, в то время как дата и календарь всегда представляют собой определенный момент времени, без такого понятия, как "просто дата", у Joda Time есть тип, представляющий это (LocalDate). Ваш код будет намного яснее, если вы сможете использовать типы, которые представляют то, что вы на самом деле пытаетесь сделать.

Существует много и много других причин использования Joda Time или java.time вместо встроенных java.util типов - они, как правило, намного лучше API. Вы всегда можете конвертировать в/из java.util.Date на границе вашего собственного кода, если вам нужно, например. для взаимодействия с базой данных.

Ответ 2

Вот то, что я использовал для получения сегодняшней даты со временем, установленным на 00:00:00:

DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");

Date today = new Date();

Date todayWithZeroTime = formatter.parse(formatter.format(today));

Ответ 3

Вы можете использовать DateUtils.truncate из библиотеки Apache Commons.

Пример:

DateUtils.truncate(new Date(), java.util.Calendar.DAY_OF_MONTH)

Ответ 4

Есть ли другой способ, чем эти два?

Да, есть.

LocalDate.now( 
    ZoneId.of( "Pacific/Auckland" ) 
)

java.time

Java 8 и более поздние версии поставляются с новым java.time пакетом. См. Tutorial. Большая часть функциональных возможностей java.time портирована на Java 6 и 7 в ThreeTen-Backport и далее адаптирована для Android в ThreeTenABP.

Подобно Joda-Time, java.time предлагает LocalDate для представления значения даты только без времени и без часового пояса.

Обратите внимание, что часовой пояс критический для определения конкретной даты. Например, в середине полуночи в Париже дата все еще "вчера" в Монреале.

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) ) ;

По умолчанию java.time использует стандарт ISO 8601 для создания строкового представления даты или даты-времени. (Еще одно сходство с Joda-Time.) Поэтому просто вызовите toString() для генерации текста типа 2015-05-21.

String output = today.toString() ; 

Ответ 5

Самый простой способ:

long millisInDay = 60 * 60 * 24 * 1000;
long currentTime = new Date().getTime();
long dateOnly = (currentTime / millisInDay) * millisInDay;
Date clearDate = new Date(dateOnly);

Ответ 6

Стандартный ответ на эти вопросы - использовать Joda Time. API лучше, и если вы используете форматировщики и синтаксические анализаторы, вы можете избежать неинтуитивного отсутствия безопасности потоков SimpleDateFormat.

Использование Joda означает, что вы можете просто сделать:

LocalDate d = new LocalDate();

Обновление:: Используя java 8, это можно получить с помощью

LocalDate date = LocalDate.now();

Ответ 7

Не имеет смысла говорить о дате без метки времени в отношении подпрограмм Date в стандартной среде исполнения Java, поскольку она по существу сопоставляется с определенной миллисекундой, а не с датой. У упомянутой миллисекунды по существу есть время суток, приложенное к ней, что делает ее уязвимой для проблем часового пояса, таких как летнее время сбережения и другие корректировки календаря. См. Почему вычитание этих двух раз (в 1927 году) дает странный результат? для интересного примера.

Если вы хотите работать с датами вместо миллисекунд, вам нужно использовать что-то еще. Для Java 8 существует новый набор методов, обеспечивающих именно то, что вы просите. Для Java 7 и более ранних версий используйте http://www.joda.org/joda-time/

Ответ 8

Хорошо, насколько я знаю, нет более простого способа добиться этого, если вы используете только стандартный JDK.

Вы можете, конечно, поместить эту логику в метод2 в статическую функцию в вспомогательном классе, например, сделать здесь в методе toBeginningOfTheDay

Затем вы можете сократить второй метод до:

Calendar cal = Calendar.getInstance();
Calendars.toBeginningOfTheDay(cal);
dateWithoutTime = cal.getTime();

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

Ответ 9

Определенно не самый правильный способ, но если вам просто нужно быстрое решение, чтобы получить дату без времени, и вы не хотите использовать стороннюю библиотеку, это должно делать

    Date db = db.substring(0, 10) + db.substring(23,28);

Мне нужна была только дата для визуальных целей и не могла Джода, поэтому я подстроил.

Ответ 10

Это простой способ сделать это:

Calendar cal = Calendar.getInstance();
SimpleDateFormat dateOnly = new SimpleDateFormat("MM/dd/yyyy");
System.out.println(dateOnly.format(cal.getTime()));

Ответ 11

Если все, что вам нужно, - это увидеть дату типа "ГГГГ-ММ-ДД" без всякого другого беспорядка, например. "Чт 21 мая 12:08:18 EDT 2015", то просто используйте java.sql.Date. Этот пример получает текущую дату:

new java.sql.Date(System.currentTimeMillis());

Также java.sql.Date является подклассом java.util.Date.

Ответ 12

Если вам нужна часть даты только для эхо-целей, то

Date d = new Date(); 
String dateWithoutTime = d.toString().substring(0, 10);

Ответ 13

// 09/28/2015
System.out.println(new SimpleDateFormat("MM/dd/yyyy").format(Calendar.getInstance().getTime()));

// Mon Sep 28
System.out.println( new Date().toString().substring(0, 10) );

// 2015-09-28
System.out.println(new java.sql.Date(System.currentTimeMillis()));

// 2015-09-28
// java 8
System.out.println( LocalDate.now(ZoneId.of("Europe/Paris")) ); // rest zones id in ZoneId class

Ответ 14

Если вам просто нужна текущая дата, без времени другая опция:

DateTime.now().withTimeAtStartOfDay()

Ответ 15

Отъезд Veyder-time. Это простая и эффективная альтернатива как java.util, так и Joda-time. Он имеет интуитивно понятный API и классы, которые представляют только даты, без временных меток.

Ответ 16

Самый простой способ, который полностью использует огромную базу данных TimeZone Java и является правильным:

long currentTime = new Date().getTime();
long dateOnly = currentTime + TimeZone.getDefault().getOffset(currentTime);

Ответ 17

Вот чистое решение без преобразования в строку и обратно, а также оно не перерасчитывает время несколько раз, когда вы reset каждый компонент времени равняется нулю. Он также использует % (модуль), а не деление, за которым следует умножение, чтобы избежать двойной операции.

Он не требует независимых сторонних зависимостей, и он ОТВЕЧАЕТ ВРЕМЯ ОТ КАЖДОГО КАЛЕНДАРНОГО объекта. Эта функция возвращает момент времени в 12 часов в часовом поясе даты (календаря), в которую вы проходите.

public static Calendar date_only(Calendar datetime) {
    final long LENGTH_OF_DAY = 24*60*60*1000;
    long millis = datetime.getTimeInMillis();
    long offset = datetime.getTimeZone().getOffset(millis);
    millis = millis - ((millis + offset) % LENGTH_OF_DAY);
    datetime.setTimeInMillis(millis);
    return datetime;
}

Ответ 18

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

  /*
    Return values:
    -1:    Date1 < Date2
     0:    Date1 == Date2
     1:    Date1 > Date2

    -2:    Error
*/
public int compareDates(Date date1, Date date2)
{
    SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");

    try
    {
        date1 = sdf.parse(sdf.format(date1));
        date2 = sdf.parse(sdf.format(date2));
    }
    catch (ParseException e) {
        e.printStackTrace();
        return -2;
    }

    Calendar cal1 = new GregorianCalendar();
    Calendar cal2 = new GregorianCalendar();

    cal1.setTime(date1);
    cal2.setTime(date2);

    if(cal1.equals(cal2))
    {
        return 0;
    }
    else if(cal1.after(cal2))
    {
        return 1;
    }
    else if(cal1.before(cal2))
    {
        return -1;
    }

    return -2;
}

Ну, не используя GregorianCalendar, возможно, вариант!