Получение компонента Time для даты или календаря Java - PullRequest
16 голосов
/ 01 сентября 2009

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

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


Редактировать: Мне было непонятно: использование одного из методов Date :: getTime () или Calendar :: getTimeInMillis не очень полезно для меня, так как они возвращают количество миллисекунд с момента эпоха (представленная этой датой или календарем), которая фактически не отделяет время суток от остальной информации.

@ Ответ Джерико, я думаю, самый близкий, но определенно это то, что мне все равно придется свернуть в метод, который я сам пишу. Это не совсем то, к чему я стремлюсь, поскольку в возвращаемое значение в миллисекундах по-прежнему включаются часы, минуты и секунды, хотя, возможно, я мог бы заставить его работать для моих целей.

Я до сих пор считаю каждый компонент отдельным , хотя, конечно, это не так. Вы можете записать время как число миллисекунд с произвольной контрольной даты, или вы можете написать то же самое время, что и year/month/day hours:minutes:seconds.milliseconds.

Это не для отображения. Я знаю, как использовать DateFormat для создания красивых строк дат.


Редактировать 2: Мой первоначальный вопрос возник из небольшого набора служебных функций, которые я написал, например:

  • Проверка, представляют ли два Date дату-время в один и тот же день;
  • Проверка, находится ли дата в диапазоне, заданном двумя другими датами, но иногда проверка включительно, а иногда нет, в зависимости от компонента времени.

Есть ли у Joda Time такая функциональность?


Редактировать 3: @ Вопрос Джона относительно моего второго требования, просто чтобы уточнить: второе требование является результатом использования моих дат для представления иногда целых дней - где компонент времени вообще не имеет значения - и иногда представляют дату-время (то есть, IMO, самое точное слово для чего-то, что содержит year/month/day и hours:minutes:seconds:...).

Когда Date представляет целый день, его части времени равны нулю (например, «компонент времени» Date - полночь), но семантика диктует, что проверка диапазона выполняется включительно в дату окончания. Поскольку я просто оставляю эту проверку до Date :: before и Date :: after, я должен добавить 1 день к дате окончания - отсюда особый случай, когда компонент времени дня в Date равен нулю.

Надеюсь, это не прояснило ситуацию.

Ответы [ 10 ]

11 голосов
/ 01 сентября 2009

Хорошо, я знаю, что это предсказуемый ответ, но ... используйте Joda Time . Он имеет отдельные представления для «даты», «мгновенного», «времени суток» и т. Д. Это более богатый API и, как правило, более разумный, чем встроенные классы, IMO.

Если это интересующий вас бит только манипуляции с датой / временем, то это может быть излишним ... но если вы используете встроенный API даты / времени для чего-то значительного Я бы настоятельно рекомендовал бы вам отойти от него в Йоду, как только вы сможете.

Кроме того, вы должны рассмотреть, какой часовой пояс вас интересует. Calendar имеет связанный часовой пояс, а Date - нет (он просто представляет момент времени, измеренный в миллисекундах от эпоха Unix).

8 голосов
/ 01 сентября 2009

Извлечение временной части дня должно зависеть от получения оставшегося количества миллисекунд при делении на количество миллисекунд в день.

long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
Date now = Calendar.getInstance().getTime();
long timePortion = now.getTime() % MILLIS_PER_DAY;

В качестве альтернативы рассмотрите возможность использования joda-time, более полнофункциональной библиотеки времени.

2 голосов
/ 01 сентября 2009

Чтобы ответить на часть этого, доступ к компоненту миллисекунды делается так:

long mill = Calendar.getInstance().getTime();

Я не знаю, что вы хотите сделать со спецификой, но вы можете использовать класс java.text.SimpleDateFormat, если он предназначен для вывода текста.

1 голос
/ 28 октября 2013

Чтобы получить только время, используя Joda-Time, используйте класс org.joda.time.LocalTime, как описано в этом вопросе, Joda-Time, Время без даты .

Что касается сравнения дат только при эффективном игнорировании времени, в Joda-Time вызовите метод withTimeAtStartOfDay() для каждого экземпляра DateTime, чтобы установить одинаковое значение времени. Вот пример кода с использованием Joda-Time 2.3, аналогичный тому, который я опубликовал сегодня в другом ответе.

    // © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.

    // Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
    // http://www.joda.org/joda-time/

    // Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
    // JSR 310 was inspired by Joda-Time but is not directly based on it.
    // http://jcp.org/en/jsr/detail?id=310

    // By default, Joda-Time produces strings in the standard ISO 8601 format.
    // https://en.wikipedia.org/wiki/ISO_8601

    // Capture one moment in time.
    org.joda.time.DateTime now = new org.joda.time.DateTime();
    System.out.println("Now: " + now);

    // Calculate approximately same time yesterday.
    org.joda.time.DateTime yesterday = now.minusDays(1);
    System.out.println("Yesterday: " + yesterday);

    // Compare dates. A DateTime includes time (hence the name).
    // So effectively eliminate the time by setting to start of day.
    Boolean isTodaySameDateAsYesterday = now.withTimeAtStartOfDay().isEqual(yesterday.withTimeAtStartOfDay());
    System.out.println("Is today same date as yesterday: " + isTodaySameDateAsYesterday);

    org.joda.time.DateTime halloweenInUnitedStates = new org.joda.time.DateTime(2013, 10, 31, 0, 0);
    Boolean isFirstMomentSameDateAsHalloween = now.withTimeAtStartOfDay().isEqual(halloweenInUnitedStates.withTimeAtStartOfDay());
    System.out.println("Is now the same date as Halloween in the US: " + isFirstMomentSameDateAsHalloween);
1 голос
/ 01 сентября 2009

Вы можете вызвать функцию getTimeInMillis () для объекта Calendar, чтобы получить время в миллисекундах. Вы можете вызвать get (Calendar.MILLISECOND) для объекта календаря, чтобы получить миллисекунды секунды. Если вы хотите отобразить время из объекта Date или Calendar, используйте класс DateFormat. Пример: DateFormat.getTimeInstance (). Format (сейчас). Существует также класс SimpleDateFormat, который вы можете использовать.

0 голосов
/ 31 января 2018

Использование Calendar API -

Раствор 1-

Calendar c = Calendar.getInstance();
String timeComp = c.get(Calendar.HOUR_OF_DAY)+":"+c.get(Calendar.MINUTE)+":"+c.get(Calendar.SECOND)+":"+c.get(Calendar.MILLISECOND);
System.out.println(timeComp);  

вывод - 13: 24: 54: 212

Раствор 2-

SimpleDateFormat time_format = new SimpleDateFormat("HH:mm:ss.SSS");
String timeComp = time_format.format(Calendar.getInstance().getTime());

выход - 15: 57: 25,518

0 голосов
/ 22 августа 2016

ТЛ; др

LocalTime lt = myUtilDate.toInstant().atZone( ZoneId.of( "America/Montreal" ) ).toLocalTime() ;

Избегайте старых классов даты и времени

Вы используете старые устаревшие классы даты и времени. Они хлопотны и сбивают с толку; избежать их.

Вместо этого используйте классы java.time. Они вытесняют старые классы, а также библиотеку Joda-Time.

Преобразование

Преобразуйте java.util.Date в Instant.

Класс Instant представляет момент на временной шкале в UTC с разрешением наносекунд .

Instant instant = myUtilDate.toInstant();

Часовой пояс

Применение часового пояса. Часовой пояс имеет решающее значение. В любой момент времени дата меняется по всему земному шару в зависимости от зоны. Например, через несколько минут после полуночи в Париже Франция - новый день, а также «вчера» в Монреале-Квебеке.

Примените ZoneId, чтобы получить объект ZonedDateTime.

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

Local… типы

Класс LocalDate представляет значение только для даты без времени суток и без часового пояса. Аналогично, LocalTime представляет время суток без даты и без часового пояса. Вы можете думать об этом как о двух компонентах, которые вместе с ZoneId составляют ZonedDateTime. Вы можете извлечь их из ZonedDateTime.

LocalDate ld = zdt.toLocalDate();
LocalTime lt = zdt.toLocalTime();

Строка

Если ваша цель - просто генерировать строки для представления пользователю, нет необходимости в типах Local…. Вместо этого используйте DateTimeFormatter для генерации строк, представляющих только часть даты или часть времени. Этот класс достаточно умен, чтобы автоматически локализовать при генерации строки.

Укажите Locale, чтобы определить (а) человеческий язык, используемый для перевода названия дня, названия месяца и т. Д., И (б) культурные нормы для решения таких вопросов, как сокращение, Прописная буква, пунктуация и т. д.

Locale l = Locale.CANADA_FRENCH ;  // Or Locale.US, Locale.ITALY, etc.

DateTimeFormatter fDate = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( locale );
String outputDate = zdt.format( fDate );

DateTimeFormatter fTime = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ).withLocale( locale );
String outputTime = zdt.format( fTime );

О java.time

Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют старые проблемные классы даты и времени, такие как java.util.Date, .Calendar и & java.text.SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java.time.

Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений.

Большая часть функциональности java.time перенесена на Java 6 & 7 в ThreeTen-Backport и дополнительно адаптирована к Android в ThreeTenABP (см. Как пользоваться… ).

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time.

0 голосов
/ 10 июля 2015

Найдите ниже решение, которое использует Joda Time и поддерживает часовые пояса. Таким образом, вы получите дату и время (в currentDate и currentTime) в текущем настроенном часовом поясе в JVM.

Обратите внимание, что Joda Time не поддерживает високосных секунд . Таким образом, вы можете быть на 26 или 27 секунд меньше истинного значения. Вероятно, это будет решено только в течение следующих 50 лет, когда накопленная ошибка будет ближе к 1 минуте, и люди начнут заботиться об этом.

Смотри также: https://en.wikipedia.org/wiki/Leap_second

/**
 * This class splits the current date/time (now!) and an informed date/time into their components:
 * <lu>
 *     <li>schedulable: if the informed date/time is in the present (now!) or in future.</li>
 *     <li>informedDate: the date (only) part of the informed date/time</li>
 *     <li>informedTime: the time (only) part of the informed date/time</li>
 *     <li>currentDate: the date (only) part of the current date/time (now!)</li>
 *     <li>currentTime: the time (only) part of the current date/time (now!)</li>
 * </lu>
 */
public class ScheduleDateTime {
    public final boolean schedulable;
    public final long millis;
    public final java.util.Date informedDate;
    public final java.util.Date informedTime;
    public final java.util.Date currentDate;
    public final java.util.Date currentTime;

    public ScheduleDateTime(long millis) {
        final long now = System.currentTimeMillis();
        this.schedulable = (millis > -1L) && (millis >= now);

        final TimeZoneUtils tz = new TimeZoneUtils();

        final java.util.Date          dmillis   = new java.util.Date( (millis > -1L) ? millis : now );
        final java.time.ZonedDateTime zdtmillis = java.time.ZonedDateTime.ofInstant(dmillis.toInstant(), java.time.ZoneId.systemDefault());
        final java.util.Date          zdmillis  = java.util.Date.from(tz.tzdate(zdtmillis));
        final java.util.Date          ztmillis  = new java.util.Date(tz.tztime(zdtmillis));

        final java.util.Date          dnow   = new java.util.Date(now);
        final java.time.ZonedDateTime zdtnow = java.time.ZonedDateTime.ofInstant(dnow.toInstant(), java.time.ZoneId.systemDefault());
        final java.util.Date          zdnow  = java.util.Date.from(tz.tzdate(zdtnow));
        final java.util.Date          ztnow  = new java.util.Date(tz.tztime(zdtnow));

        this.millis       = millis;
        this.informedDate = zdmillis;
        this.informedTime = ztmillis;
        this.currentDate  = zdnow;
        this.currentTime  = ztnow;
    }
}



public class TimeZoneUtils {

    public java.time.Instant tzdate() {
        final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
        return tzdate(zdtime);
    }
    public java.time.Instant tzdate(java.time.ZonedDateTime zdtime) {
        final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
        final java.time.Instant instant = zddate.toInstant();
        return instant;
    }

    public long tztime() {
        final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
        return tztime(zdtime);
     }
    public long tztime(java.time.ZonedDateTime zdtime) {
        final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
        final long millis = zddate.until(zdtime, java.time.temporal.ChronoUnit.MILLIS);
        return millis;
    }
}
0 голосов
/ 01 сентября 2009

Почему вы хотите разделить их? Если вы хотите выполнить какую-либо арифметику с частью времени, вы быстро попадете в беду. Если вы достанете 23:59 и добавите минуту, теперь, когда ваше время и день разделены, вы облажались - у вас будет неправильное время и неправильная дата.

Если вы просто хотите отобразить их, тогда применение различных простых форматов даты должно дать вам именно то, что вы хотите.

Если вы хотите манипулировать датой, я предлагаю вам получить длинные значения и основывать все на этом. В любой момент вы можете взять это долго и применить формат, чтобы минуты / часы / секунды отображались довольно легко.

Но я просто немного обеспокоен концепцией манипулирования днем ​​и временем по отдельности, похоже, что я могу открыть червяков. (Не говоря уже о проблемах с часовым поясом!).

Я вполне уверен, что именно поэтому у Java нет простого способа сделать это.

0 голосов
/ 01 сентября 2009

Если все, что вас беспокоит, это поместить его в строку для отображения или сохранения, просто создайте SimpleDateFormat, который отображает только часть времени, например, новый SimpleDateFormat («ЧЧ: мм: сс»). Конечно, дата все еще находится в объекте Date, но вам все равно.

Если вы хотите сделать арифметику, например, возьмите два объекта Date и найдите, сколько секунд они разнесут, игнорируя часть даты, так что "2009-09-01 11:00:00" минус "1941-12 -07 09:00:00 "равняется 2 часам, тогда я думаю, что вам нужно использовать решение, подобное Jherico: найдите время и возьмите его модуль 1 день.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...