Date.getTime() в Java, возвращая разное время на другом сервере

Мне нужно рассчитать значение, основанное на датах. Итак, я сначала разбираю дату, используя класс формата даты, а затем использую getTime() чтобы получить миллисекунды. С этими миллисекундами я вычислю некоторое значение. Но getTime() возвращает разные значения на разных серверах. Мы развиваемся здесь, в Индии, где я получаю правильное значение, но на американском сервере я получаю другое значение.

Сценарий:

public class Test {

    public static void main(String[] args) throws ParseException {

        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");

        String now = "11/03/2018";

        Date UsualDateformat = sdf.parse(now);

        System.out.println(UsualDateformat.getTime());
    }
}

Выше приведен пример кода, но мой настоящий код - это правило в файле drl (drools). Эта программа возвращает "1541183400000", который я конвертирую в дату "Сб 3 ноября 2018 00:00:00", но на американском сервере я получаю "1541217600000", равный дате "Сб 3 ноября 2018 09:30:00". Поэтому, когда я использую это значение, я получаю проблему форматирования предельной десятичной точки. Как решить эту проблему?

Заранее спасибо!

4 ответа

Вам необходимо установить часовой пояс на SimpleDateFormat, чтобы он был согласованным на серверах в разных регионах. Например:

public class Test {

    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        ....
    }

}

Вы получаете эти разные значения, потому что разница во времени между вашим сервером в США и тем, что находится в Индии, составляет 9 часов 30 минут.

Это не имеет ничего общего с плавающей точкой, но с часовыми поясами.

Один из способов решить эту проблему - работать всегда в одном часовом поясе (например, в Индии).

Этот фрагмент кода может работать для вас,

public static String getGmtTime(String timezone) {
    return ZonedDateTime
            .now()
            .withZoneSameInstant(ZoneId.of(timezone))
            .toLocalDateTime()
            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}

проходить timezone как America/Los_Angeles чтобы получить время с правильным часовым поясом, часовые пояса можно найти здесь

java.time

Я рекомендую вам использовать java.time Для этого также известен как JSR-310. Классы, которые вы используете, Date а также SimpleDateFormatустарели, и SimpleDateFormat в частности, он имеет репутацию выдающего удивительные результаты, что можно сказать также произошло в вашем случае. Современный API, как правило, гораздо приятнее работать.

Как я думаю, вы уже подозревали, что ваша проблема связана с тем, что ваши серверы работают в разных часовых поясах, и преобразование даты в миллисекунды, так как эпоха является зависимой от часового пояса операцией, поскольку эпоха всегда совпадает с моментом времени. (1 января 1970 года в полночь по UTC). Как mweiss я использую UTC для преобразования, чтобы убедиться, что он дает тот же результат, независимо от часового пояса сервера:

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM/dd/yyyy");
    String now = "11/03/2018";
    LocalDate date = LocalDate.parse(now, dtf);
    long millisInUtc = date.atStartOfDay(ZoneOffset.UTC)
            .toInstant()
            .toEpochMilli();
    System.out.println(millisInUtc);

Поскольку мой код стоит, он печатает

1541203200000

Это между значениями, которые вы получили в Индии и США, потому что UTC находится между этими двумя часовыми поясами. Если вы считаете более правильным использовать, например, время Азии / Калькутты, просто замените ZoneId.of("Asia/Kolkata") вместо ZoneOffset.UTC в коде, и вы должны получить тот же вывод, который вы уже получили, когда запускали свой код на своем сервере в Индии (пожалуйста, не забудьте переименовать переменную тоже).

Мой код немного длиннее вашего. Я считаю это преимуществом в этом случае. Да, в самом деле. Код, использующий java.time ясно указывает, что мы используем время в начале дня (0:00 полуночи) и что для конвертации мы используем часовой пояс или смещение. Это заставляет вас, как программиста, задуматься об этих проблемах, и вам вряд ли удастся написать код, который даст неожиданные результаты в разных часовых поясах, то есть ваша проблема никогда не возникнет. В то же время, читатель четко заявляет, что операция зависит от часового пояса, и что вы сделали сознательный выбор, какую зону использовать. Эти преимущества стоят еще нескольких строк кода.

Другие вопросы по тегам