Java - автоматическая генерация текущего дня + время ввода пользователя - PullRequest
0 голосов
/ 06 мая 2018

На данный момент я получил класс 'Flight' с типами данных Date; дата отправления и прибытия.

Добавление рейсов происходит путем ввода данных пользователем. День должен автоматически быть текущей датой, а время - выбором пользователя. Это означает, что человек должен ввести только ЧЧ: мм.

На данный момент это немного путает со всеми вариантами выбора; Отметка времени, дата, местное время и т. Д.

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

Кто-нибудь знает, как это сделать, или может дать некоторые советы / лучшие практики?

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

ТЛ; др

LocalDateTime.of(                 // A `LocalDateTime` represents a set of *potential* moments along a range of about 26-27 hours. Not an actual moment, not a point on the timeline.
    LocalDate.systemDefault() ,   // Get the JVM’s current default time zone. Can change at any moment *during* runtime. When crucial, always confirm with the user.
    LocalTime.parse( "14:57" )    // Parse a string in standard ISO 8601 format as a time-of-day without regard for time zone or offset-from-UTC.
)                                 // Returns a `LocalDateTime` object.
.atZone(                          // Determine an actual moment, a point on the timeline.
    ZoneId( "Africa/Tunis" )      // Specify a time zone as `Continent/Region`, never as 3-4 letter pseudo-zones such as `PST`, `CST`, or `IST`.
)                                 // Returns a `ZonedDateTime` object.
.toInstant()                      // Extracts a `Instant` object from the `ZonedDateTime` object, always in UTC by default.

Подробнее

На данный момент это немного сбивает с толку

Обработка даты и времени - очень запутанная работа.

Советы:

  • Забудьте о своем часовом поясе. Думайте в терминах UTC , а не в своем собственном приходском часовом поясе.
  • Узнайте разницу между реальными моментами (точками на временной шкале) и приближениями даты и времени, которые не на временной шкале, часто называемыми «локальными» значениями.
  • Будьте внимательны при чтении переполнения стека или других мест в Интернете о дате и времени. Вы столкнетесь с плохим советом и многими неправильными решениями.

со всеми вариантами выбора; Отметка времени, дата, местное время и т. Д.

Никогда не используйте проблемные старые унаследованные классы даты и времени, включенные в самые ранние версии Java. Никогда не используйте java.sql.Timestamp, java.util.Date, java.util.Calendar и т. Д.

➡ Использовать только классы в java.time пакете .

Классы java.time являются лидирующей в отрасли средой обработки данных и времени. Чрезвычайно хорошо продуманный и продуманный, с уроками, извлеченными из проекта Joda-Time , он добился успеха.

Кто-нибудь знает, как это сделать, или может дать некоторые советы / лучшие практики?

Вы можете сожалеть, что спросили. Продолжайте читать.

На данный момент я получил класс 'Flight' с типами данных Date; дата отправления и прибытия.

Итак, определите класс Flight.

В реальной жизни полеты в будущем происходят достаточно далеко, и мы рискуем, что политики изменят определение часового пояса. Чаще всего эти изменения включают принятие / удаление / изменение Летнее время (DST) . Но произвольные изменения периодически вносятся по разным причинам. Мы могли бы обсудить мудрость / здравомыслие таких изменений, но факт в том, что они случаются. Они случаются довольно часто, так как политики, кажется, странно склонны к внесению этих изменений во всем мире во многих странах. И почти все они делают это с небольшим предупреждением, иногда всего за несколько недель. Или даже без предупреждения, как Северная Корея на этой неделе .

У меня нет понимания того, как на самом деле работают авиалинии, но из просмотра расписаний авиакомпаний и различных чтений, кажется, они пытаются сохранить свои расписания, используя зонированное время вылетающего населенного пункта. Таким образом, если вылет рейса запланирован на 6 часов утра, они сохраняют расписание рейсов на день раньше, в день и на следующий день после перехода на летнее время. Если это действительно общее намерение, это означает, что время убийства при одной посадке на летнее время усаживается без присмотра, и в то же время пытается сэкономить час на противоположном отключении летнего времени. Очевидно, Amtrak использует эту практику для своих поездов. Давайте продолжим с этим подходом.

Использование этого «мнимого» подхода к расписанию означает, что мы не можем точно определить точный момент, когда наступит 6 часов утра в будущем. Поэтому нам нужно записать наше желание на эту дату и это время суток без применения часового пояса. Но мы должны записать желаемый часовой пояс, чтобы мы знали, в каком контексте мы можем позже определить точный момент, когда достаточно близко по времени, чтобы нам не пришлось беспокоиться об изменении зоны.

Поэтому мы используем LocalDate и LocalTime типов, поскольку у них намеренно отсутствует какое-либо понятие часовой пояс (имя в Continent/Region формат) или смещение от UTC (количество часов, минут и секунд).

Класс ZoneId представляет часовой пояс.

Я использую слово Unzoned в именах, чтобы напомнить нам, что эти значения не представляют фактические моменты на временной шкале. Слово «местный» обычно сбивает с толку новичков.

public class Flight {
    private String flightNumber;
    private LocalDate departureDateUnzoned;
    private LocalTime departureTimeUnzoned;
    private ZoneId departureZoneId ;
}

Что касается прибытияКроме того, сохраните ожидаемый промежуток времени для этого рейса, а не дату и время прибытия. Вы можете рассчитать прибытие, поэтому нет необходимости хранить его. Класс Duration отслеживает количество часов, минут, секунд и доли секунды.

Чтобы вычислить прибытие, давайте вернем одно значение, используя класс LocalDateTime, который просто комбинирует LocalDate с LocalTime. Мы могли бы использовать этот тип для создания единственной departureUnzoned переменной-члена в нашем определении класса. Я использовал отдельные LocalDate и LocalTime в качестве строительных блоков, чтобы вы могли понять их. Поэтому многие программисты используют свою интуицию, а не документацию, чтобы предположить, что LocalDateTime означает определенный момент в местности, когда на самом деле это означает прямо противоположное. (Вы найдете много неправильных ответов на переполнение стека, советуя LocalDateTime, когда на самом деле Instant или ZonedDateTime следует использовать.)

Давайте добавим метод для расчета этого прибытия.

public class Flight {
    private String flightNumber;
    private LocalDate departureDateUnzoned;
    private LocalTime departureTimeUnzoned;
    private ZoneId departureZoneId;
    private Duration duration;

    public LocalDateTime arrivalDateTimeUnzoned () {
        LocalDateTime departureUnzoned = LocalDateTime.of( this.departureDateUnzoned , this.departureTimeUnzoned );
        LocalDateTime ldt = departureUnzoned.plus( this.duration );
        return ldt;
    }
}

Но возвращенное значение LocalDateTime не учитывает часовой пояс. Обычно авиакомпании и поезда сообщают клиентам ожидаемое время прибытия, скорректированное с учетом часового пояса этого региона. Итак, нам нужен часовой пояс прибытия. И мы можем использовать эту зону при расчете прибытия, таким образом получая ZonedDateTime. ZonedDateTime - это особый момент, - точка на временной шкале, в отличие от LocalDateTime. Но помните, что если мы планируем полеты в будущее, рассчитанный ZonedDateTime изменится, если наш код будет запущен после того, как политики переопределят часовой пояс.

public class Flight {
    private String flightNumber;
    private LocalDate departureDateUnzoned;
    private LocalTime departureTimeUnzoned;
    private ZoneId departureZoneId;
    private Duration duration;
    private ZoneId arrivalZoneId;

    public ZonedDateTime arrivalDateTimeZoned () {
        ZonedDateTime departureZoned = ZonedDateTime.of( this.departureDateUnzoned , this.departureTimeUnzoned , this.departureZoneId );
        ZonedDateTime zdt = departureZoned.plus( this.duration );
        return zdt;
    }
}

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

Мы можем запросить текущий часовой пояс JVM по умолчанию.

ZoneId userZoneId = ZoneId.systemDefault() ;

Но когда это важно, вы должны подтвердить это с пользователем.

ZoneId userZoneId = ZoneId.of( "America/Montreal" ) ; 

Так что теперь мы можем добавить запрошенный вами конструктор, передав время дня (LocalTime и угадав часовой пояс, используя текущее значение по умолчанию в JVM.

Но нам все еще нужны все остальные части. Так что дефолт с датой нас не сильно спасет.

public class Flight {
    private String flightNumber;
    private LocalDate departureDateUnzoned;
    private LocalTime departureTimeUnzoned;
    private ZoneId departureZoneId;
    private Duration duration;
    private ZoneId arrivalZoneId;

    // Constructor
    public Flight ( String flightNumber , LocalTime departureTimeUnzoned , ZoneId departureZoneId , Duration duration , ZoneId arrivalZoneId ) {
        this.flightNumber = flightNumber;
        this.departureTimeUnzoned = departureTimeUnzoned;
        this.departureZoneId = departureZoneId;
        this.duration = duration;
        this.arrivalZoneId = arrivalZoneId;

        // Determine today’s date using JVM’s current default time zone. Not advisable in many business scenarios, but specified by our Question at hand.
        ZoneId z = ZoneId.systemDefault();
        LocalDate today = LocalDate.now( z );
        this.departureDateUnzoned = today;
    }

    public ZonedDateTime arrivalDateTimeZoned () {
        ZonedDateTime departureZoned = ZonedDateTime.of( this.departureDateUnzoned , this.departureTimeUnzoned , this.departureZoneId );
        ZonedDateTime zdt = departureZoned.plus( this.duration );
        return zdt;
    }
}

Давайте добавим toString метод отчетности.

Мы представляем значения даты и времени в виде строк в стандартных форматах ISO 8601 . Классы java.time используют эти стандартные форматы при разборе / генерации строк. Z на конце произносится Zulu и означает UTC.

Несмотря на то, что авиакомпании и поезда сообщают о времени своих клиентов в часовых поясах регионов, мы можем предположить, что они используют только UTC для своих целей. Класс Instant специально представляет значения в формате UTC. Таким образом, наши toString извлекают Instant объекты из ZonedDateTime объектов.

И мы добавляем main метод для демонстрации. Вот полный класс, с import и т. Д.

package com.basilbourque.example;

import java.time.*;

public class Flight {
    private String flightNumber;
    private LocalDate departureDateUnzoned;
    private LocalTime departureTimeUnzoned;
    private ZoneId departureZoneId;
    private Duration duration;
    private ZoneId arrivalZoneId;

    // Constructor
    public Flight ( String flightNumber , LocalTime departureTimeUnzoned , ZoneId departureZoneId , Duration duration , ZoneId arrivalZoneId ) {
        this.flightNumber = flightNumber;
        this.departureTimeUnzoned = departureTimeUnzoned;
        this.departureZoneId = departureZoneId;
        this.duration = duration;
        this.arrivalZoneId = arrivalZoneId;

        // Determine today’s date using JVM’s current default time zone. Not advisable in many business scenarios, but specified by our Question at hand.
        ZoneId z = ZoneId.systemDefault();
        LocalDate today = LocalDate.now( z );
        this.departureDateUnzoned = today;
    }

    public ZonedDateTime arrivalDateTimeZoned () {
        ZonedDateTime departureZoned = ZonedDateTime.of( this.departureDateUnzoned , this.departureTimeUnzoned , this.departureZoneId );
        ZonedDateTime zdt = departureZoned.plus( this.duration );
        return zdt;
    }

    @Override
    public String toString () {
        ZonedDateTime departureZoned = ZonedDateTime.of( this.departureDateUnzoned , this.departureTimeUnzoned , this.departureZoneId );
        String flightInUtc = departureZoned.toInstant().toString() + "/" + this.arrivalDateTimeZoned().toInstant().toString();
        return "Flight{ " +
                "flightNumber='" + this.flightNumber + '\'' +
                " | departureDateUnzoned=" + this.departureDateUnzoned +
                " | departureTimeUnzoned=" + this.departureTimeUnzoned +
                " | departureZoneId=" + this.departureZoneId +
                " | departureZoned=" + departureZoned +
                " | duration=" + this.duration +
                " | arrivalZoneId=" + this.arrivalZoneId +
                " | calculatedArrival=" + this.arrivalDateTimeZoned() +
                " | flightInUtc=" + flightInUtc +
                " }";
    }

    public static void main ( String[] args ) {
        LocalTime lt = LocalTime.of( 6 , 0 ); // 6 AM.
        Flight f = new Flight( "A472" , lt , ZoneId.of( "America/Los_Angeles" ) , Duration.parse( "PT6H37M" ) , ZoneId.of( "America/Montreal" ) );
        String output = f.toString();
        System.out.println( output );
    }
}

При запуске.

Flight {flightNumber = 'A472' | flightDateUnzoned = 2018-05-06 | выслать время отправлено = 06:00 | вылетZoneId = Америка / Лос-Анджелес | вылет = 2018-05-06T06: 00-07: 00 [America / Los_Angeles] | длительность = PT6H37M | прибытиеZoneId = Америка / Монреаль | рассчитанный доход = 2018-05-06T12: 37-07: 00 [America / Los_Angeles] | flightInUtc = 2018-05-06T13: 00: 00Z / 2018-05-06T19: 37: 00Z}

Чтобы использовать это с консоли, спросите пользователя о времени суток в 24-часовых часах. Разбор входной строки.

String input = "14:56" ;  // 24-hour clock.
LocalTime lt = LocalTime.parse( input ) ;

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


О java.time

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

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

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

Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

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

0 голосов
/ 06 мая 2018

Поскольку вы сказали, что разрабатываете настольное приложение и вам нужна текущая дата (на ПК), вы можете использовать комбинацию LocalDate и LocalTime для достижения своей цели.

Вот код:

public static void main(String[] args) {
LocalDate currentDate = LocalDate.now();
LocalTime userInputTime = null;

Scanner sc = new Scanner(System.in);
String dateTimeLine = sc.nextLine();
sc.close();

DateTimeFormatter dt = DateTimeFormatter.ofPattern("HH:mm");
userInputTime = LocalTime.parse(dateTimeLine,dtf);

System.err.println(LocalDateTime.of(currentDate, userInputTime));
}

Сначала вы используете LocalDate.now(), чтобы сгенерировать текущую дату (только дату, без часов, минут и секунд).

Далее мы используем Scanner, чтобы прочитать строку, введенную пользователем. Чтобы преобразовать строку в LocalTime (этот класс содержит информацию только о времени в дне, поэтому он имеет значения для часов, минут, секунд и наносекунд), мы должны определить DateTimeFormatter. DateTimeFormatter определяет, как строка будет преобразована в LocalTime экземпляр.

В коде, который я только что написал, я сказал, что ввод строки будет иметь тип «часы: минуты». Например, возможные значения:

"10:25" - 10 часов 25 минут,

"23:00" - 23 часа и 0 минут,

"02:13" - 2 часа 13 минут.

После того, как мы создадим объект LocalTime, все, что нам нужно сделать, это присоединиться к объектам даты и времени, чтобы создать объект LocalDateTime, который выполняется в этой строке:

LocalDateTime.of(currentDate, userInputTime)

Итак, допустим, что дата на вашем текущем ПК - 2018-05-06. Если вы запустите программу и введете в консоль 10:50, то на выходе должен быть объект LocalDateTime с датой 2018-05-06 в качестве даты и 10 часами и 50 минутами в качестве времени дня.

Важно отметить, что эта строка:

userInputTime = LocalTime.parse(dateTimeLine,dtf);

выдаст java.time.format.DateTimeParseException, если введенная пользователем строка не соответствует требуемому формату.

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