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 полуночи) и что для конвертации мы используем часовой пояс или смещение. Это заставляет вас, как программиста, задуматься об этих проблемах, и вам вряд ли удастся написать код, который даст неожиданные результаты в разных часовых поясах, то есть ваша проблема никогда не возникнет. В то же время, читатель четко заявляет, что операция зависит от часового пояса, и что вы сделали сознательный выбор, какую зону использовать. Эти преимущества стоят еще нескольких строк кода.