Если вы хотите только использования фактической Московской зоны смещения для отображения исторической метки, то вы можете использовать этот код:
String dateString = "1990-05-03T20:00:00.000Z";
DateTimeFormatter inputFormatter =
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").withZone(DateTimeZone.UTC);
DateTime dt = inputFormatter.parseDateTime(dateString);
System.out.println(dt); // 1990-05-03T20:00:00.000Z
// only use actual offset for Moscow
DateTimeZone zoneOffset =
DateTimeZone.forOffsetMillis(
DateTimeZone.forID("Europe/Moscow").getOffset(DateTime.now())
);
DateTimeFormatter outputFormatter =
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").withZone(zoneOffset);
String result = outputFormatter.print(dt);
System.out.println(result); // 1990-05-03T23:00:00.000+0300
Тем не менее тот же момент, как раз с различным смещением и местного времени часть из форму, которую вы ищете.
О ваш комментарий, как синтаксический анализ UTC времени с сервера:
String input = "2016-12-10T13:40:38.595";
DateTime utc =
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS").parseLocalDateTime(input)
.toDateTime(DateTimeZone.UTC);
System.out.println(utc); // 2016-12-10T13:40:38.595Z
Как отправить текущее время устройства, как UTC к серверу, если данные устройства являются неправильными?
Прежде всего, я считаю, что это лучший дизайн, если нет необходимости отправлять текущую временную метку клиента на сервер, потому что сервер должен использовать свои собственные часы для регистрации метки времени при получении клиентских сообщений. Это эффективно препятствует поддельным клиентам отправлять какое-либо бессмысленное время.
В противном случае, если и tz-данные, и часы устройства (через System.currentTimeMillis()
) ошибочны, но временная метка локального устройства по-прежнему правильная, как указано в ваших комментариях (допустимые значения полей для года-месяца-дня-часа-минуты) то можно применить следующий обходной путь:
// incorrect platform data from device clock or outdated tz-data
long platformMillis = System.currentTimeMillis();
int offsetMillis = TimeZone.getDefault().getOffset(platformMillis);
DateTimeZone tzPlatform = DateTimeZone.forOffsetMillis(offsetMillis); // +04 on your device
// we assume correct local time if the errors of platform data compensate each other
LocalDateTime ldt = new LocalDateTime(new Date(platformMillis), tzPlatform);
// now we combine local timestamp with the tz-data of Joda-Time (hopefully up-to-date)
long utcMillis = ldt.toDateTime(DateTimeZone.getDefault()).getMillis();
Side примечание: Моя библиотека Time4A позволяет более короткое решение.
Moment now = SystemClock.inPlatformView().now().inStdTimezone();
long utcMillis = TemporalType.MILLIS_SINCE_UNIX.from(now);
Я думаю, ничего плохого. 1990-05-03 - в летнее время (май), поэтому Joda-Time использует летнее смещение +04: 00 для Европы/Москвы. Может быть, вы просто смущены, потому что на самом деле Москва в зимнее время. –
@MenoHochschild С 2014 года в России есть только зимнее время, и мы не меняем время каждый год. Как я могу отключить летнее/зимнее время в Joda-Time? – preceptron