Как конвертировать формат строки времени с другим часовым поясом в Android - PullRequest
0 голосов
/ 08 июля 2019

У меня есть один формат строки времени, например yyyy-MM-dd'T'HH:mm:ss.SSSSSS с часовым поясом «GMT + 05: 30».Мне нужно конвертировать этот формат в yyyy-MM-dd'T'HH:mm:ss.SSS'Z' формат с другим часовым поясом - «GMT0: 00».Я пишу ниже функцию, чтобы преобразовать временную строку с другим часовым поясом.Это работает нормально, но не может изменить время.

public static String getUTCDate(String dateString) {
    String oldDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS";
    String newDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String result = "";
    SimpleDateFormat simpleDateFormatOld;
    SimpleDateFormat simpleDateFormatNew;

    try {
        simpleDateFormatOld = new SimpleDateFormat(oldDateFormat,Locale.US);
        simpleDateFormatNew = new SimpleDateFormat(newDateFormat,Locale.US);
        simpleDateFormatNew.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
        result = simpleDateFormatNew.format(simpleDateFormatOld.parse(dateString));
    }
    catch(Exception e) {
        ExceptionHandler.handleException(e);
    }
    return result;
}

Пример : я передал 2019-07-11T21:28:02.8469576 строку даты и времени.Но взамен я получил 2019-07-11T21:28:02.846Z строку даты и времени без изменения времени.

Как мне обновить время строки?

Ответы [ 4 ]

1 голос
/ 08 июля 2019

В большинстве случаев не следует преобразовывать точку во времени из одного строкового формата в одном часовом поясе в другой строковый формат в другом часовом поясе.В вашей программе храните дату и время в надлежащих объектах даты и времени, а не в строках (точно так же, как вы не будете хранить целочисленные значения или значения с плавающей точкой в ​​строке).Если вам просто нужен момент времени (а не исходное смещение по Гринвичу, +05: 30), класс Instant является правильным для использования.Когда ваша программа принимает строковый ввод, сначала проанализируйте и преобразуйте его в Instant и сохраните как таковой.Только когда вам нужно передать строковый вывод, отформатируйте время обратно в строку и передайте его.

java.time и ThreeTenABP

Разбор и преобразование ввода

    ZoneId originalZone = ZoneId.of("Asia/Kolkata");

    Instant time = LocalDateTime.parse("2019-07-11T21:28:02.8469576")
            .atZone(originalZone)
            .toInstant();

    System.out.println(time);

Преобразованное время печатается как:

2019-07-11T15: 58: 02.846957600Z

Для большинства целей не выделяйте времязона как голое смещение по Гринвичу.Именованный часовой пояс лучше объясняет читателю, почему эта зона была выбрана, и является более перспективной в случае изменения смещения (что происходит чаще, чем вы думаете).Я использую тот факт, что ваша строка в формате ISO 8601.В этом случае нам не нужно указывать явный форматер.Кстати, ваша строка примера имеет 7 десятичных знаков в секундах, а ваш oldDateFormat, кажется, хочет 6. Здесь не имеет значения, поскольку LocalDateTime.parse принимает все от 0 до 9 десятичных знаков.

Формат вывода

Требуемый вывод - это другой вариант ISO 8601. Приведенный выше вывод очень похож, потому что это тоже ISO 8601, только слишком много десятичных знаков.Итак, давайте применим явное форматирование на этот раз:

    ZoneOffset newOffset = ZoneOffset.UTC;
    DateTimeFormatter newFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .appendPattern("HH:mm:ss.SSSX")
            .toFormatter();

    String formattedUtcDateTime = time.atOffset(newOffset).format(newFormatter);
    System.out.println(formattedUtcDateTime);

2019-07-11T15: 58: 02.846Z

Мы видим, что java.time, современная JavaAPI даты и времени вынуждает нас указывать смещение часового пояса, поэтому забыть сделать это (как вы, похоже, сделали в коде вопроса, вызывая неожиданный вывод) просто невозможно.

Я рекомендую против SimpleDateFormat и TimeZone

Классы даты и времени, которые вы пытались использовать, SimpleDateFormat и TimeZone, плохо спроектированы и давно устарели, первые, в частности, печально известны своими проблемами.Также не может , чтобы SimpleDateFormat мог правильно анализировать 6 или 7 десятичных знаков по секундам;он поддерживает только миллисекунды, ровно три знака после запятой.Вместо этого я использую java.time, современный Java-интерфейс даты и времени.Мне гораздо приятнее работать.

Вопрос: Могу ли я использовать java.time на Android?

Да, java.time прекрасно работает на старых и новых устройствах Android.Для этого требуется как минимум Java 6 .

  • В Java 8 и более поздних версиях и на более новых устройствах Android (от уровня API 26) современный API поставляется встроенным.
  • В Java 6 и 7 получают ThreeTen Backport, бэкпорт современных классов (ThreeTen для JSR 310; см. Ссылки внизу).
  • На (более старых) Android используется версия ThreeTen для AndroidBackport.Это называется ThreeTenABP.И убедитесь, что вы импортируете классы даты и времени из org.threeten.bp с подпакетами.

Ссылки

0 голосов
/ 08 июля 2019

РЕДАКТИРОВАТЬ: Попробуйте этот метод:

    public static String getUTCDate(String dateString) {
    Log.d(TAG,"input : "+dateString);
    String oldDateFormat = "yyyy-MM-dd'T'HH:mm:ss";
    String newDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String result = "";
    SimpleDateFormat simpleDateFormatOld;
    SimpleDateFormat simpleDateFormatNew;

    try {
        simpleDateFormatOld = new SimpleDateFormat(oldDateFormat, Locale.US);
        simpleDateFormatNew = new SimpleDateFormat(newDateFormat,Locale.US);
        simpleDateFormatOld.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
        simpleDateFormatNew.setTimeZone(TimeZone.getTimeZone("GMT0:00"));
        result = simpleDateFormatNew.format(simpleDateFormatOld.parse(dateString));
    }
    catch(Exception e) {
        ExceptionHandler.handleException(e);
    }
    return result;
}

Есть 2 изменения: 1. Установите часовой пояс для нового формата.

simpleDateFormatNew.setTimeZone(TimeZone.getTimeZone("GMT0:00"));
  1. Удалить шаблон в миллисекундах из oldDateFormat.

    String oldDateFormat = "гггг-ММ-дд'Т'ЧЧ: мм: сс";

0 голосов
/ 08 июля 2019

Я решил эту проблему, добавив часовой пояс также для oldDateFormat.

Например:

simpleDateFormatOld.setTimeZone(TimeZone.getTimeZone("GMT+5:30"));
simpleDateFormatNew.setTimeZone(TimeZone.getTimeZone("GMT+0:00"));
0 голосов
/ 08 июля 2019

Попробуйте это:

  public static String getUTCDate(String dateString) {
    String oldDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS";
    String newDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String result = "";
    SimpleDateFormat simpleDateFormatOld;
    SimpleDateFormat simpleDateFormatNew;

    try {
        simpleDateFormatOld = new SimpleDateFormat();
        simpleDateFormatOld.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
        simpleDateFormatOld.applyPattern(oldDateFormat);
        simpleDateFormatNew = new SimpleDateFormat(newDateFormat, Locale.US);
        result = simpleDateFormatNew.format(simpleDateFormatOld.parse(dateString));
    }
    catch(Exception e) {
        e.printStackTrace();
    }
    return result;
}

Это сработало для меня. Он просто устанавливает часовой пояс объекта simpleDataFormatOld перед применением к нему шаблона даты.

...