конвертировать utc в местное время в иране - PullRequest
0 голосов
/ 02 июня 2018

Я пытаюсь преобразовать время UTC в местное время, минута работает хорошо, но час всегда имеет 1 час спустя, например, если время UTC 04:55, мои телефонные часы 9:25, но мой код генерирует 8:25

   String dateStr = "04:55";
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date = null;
        try {
            date = df.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        df.setTimeZone(TimeZone.getDefault());
        String formattedDate = df.format(date);

        time.setText(String.valueOf(formattedDate));

Ответы [ 4 ]

0 голосов
/ 02 июня 2018

Нет летнего времени в Иране в 1970 году

Часовой пояс для Ирана, Asia/Tehran, имеет значение Летнее время (летнее время) летом 2018 года, но не сделал этого обратно в1970.

Летом 2018 года Иран опережает UTC на четыре с половиной часа, а не на три с половиной.Таким образом, изменение с 4:55 по UTC должно привести к 9:25 в летний день, а не к 8: 25.

System.out.println(
        OffsetDateTime.of(
                LocalDate.of( 2018 , Month.JUNE , 1 ) ,
                LocalTime.parse( "04:55" ) ,
                ZoneOffset.UTC
        )
       .atZoneSameInstant(
           ZoneId.of( "Asia/Tehran" )
       )
);

2018-06-01T09: 25 + 04: 30 [Азия /Тегеран]

Но я подозреваю, что ваш код по умолчанию использует ссылку эпохи дату первого момента 1970 года в UTC при разборе вашей строки, 1970-01-01T00: 00: 00Zпотому что вы злоупотребляете этим классом, пытаясь разобрать время суток без указания даты.

В 1970 году Иран не наблюдал переход на летнее время (DST).Таким образом, смещение было на три с половиной часа до UTC летом 1970 года по сравнению с четырьмя с половиной часами до UTC летом 2018 года.

System.out.println(
    OffsetDateTime.of(
        LocalDate.EPOCH ,
        LocalTime.parse( "04:55" ) ,
        ZoneOffset.UTC
    )
        .atZoneSameInstant(
            ZoneId.of( "Asia/Tehran" )
        )
);

1970-01-01T08: 25+03:30 [Азия / Тегеран]

Неправильные классы

Вы используете неправильные классы.

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

Вы используете неприятные, плохо продуманные классы даты и времени, java.util.Date & java.text.SimpleDateFormat.Они были вытеснены несколько лет назад классами java.time .Избегайте старых классов полностью.Используйте только классы, найденные в java.time пакете .

Время дня

Анализ строки времени дня.

LocalTime.parse( "04:55" )

Получите текущее время суток.

LocalTime.now()                  // Capture the current time of day per the JVM’s current default time zone.

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

LocalTime.now(
    ZoneId.systemDefault()       // Capture the current time of day by explicitly asking for the JVM’s current default time zone.
)

Или укажите конкретный часовой пояс.

LocalTime.now( 
    ZoneId.of( "Asia/Kabul" )  // Capture the current time-of-day as seen in the wall-clock time used by the people of a particular region (a time zone).
)

9: 25

Получите текущее время в UTC.

LocalTime.now( 
    ZoneOffset.UTC
)

04: 55

LocalTime

Если у вас есть строка ввода, такая как «04:55», анализируйте как LocalTime объект.Этот класс представляет время суток без даты и без часового пояса.

String input = "04:55" ;
LocalTime lt = LocalTime.parse( input ) ;

Терминология

Я пытаюсь преобразовать время UTC в местное время

Ваша фраза «местное время» имеет особое значение при обработке даты и времени.К сожалению, это значение является противоположным вашего намерения.Слово «местный», как видно из классов * java.time.Local… », означает любой населенный пункт или все населенных пунктов, а не какой-либо один конкретный населенный пункт.

ИтакLocalTime объект не имеет реального значения, пока не будет прикреплен к дате и помещен в контекст часового пояса (или смещения от UTC).

Часовые пояса

Если время UTC - 04:55, часы моего телефона - 9: 25

Это означает, что текущий часовой пояс по умолчанию вашей JVM -используя смещение от UTC за четыре с половиной часа до UTC, +04:30.Согласно этому списку часовых поясов как , управляемым IANA , в настоящее время используется только один часовой пояс, использующий это смещение: Asia/Kabul.

Чтобы полностью представить текущий момент, вам нужны дата и время дня, а также зона / смещение.Чтобы зафиксировать текущий момент, используйте Instant.Класс Instant представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) цифр десятичной дроби).

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

Чтобы увидеть тот же момент в вашем часовом поясе, примените ZoneId, чтобы получить ZonedDateTime.

ZoneId zKabul = ZoneId.of( "Asia/Kabul" ) ;
ZonedDateTime zdt = instant.atZone( zKabul ) ;

Если вам действительно нужна только часть времени этого значения, извлеките LocalTime.Это может быть полезно для рендеринга в пользовательском интерфейсе, но вряд ли полезно в вашей бизнес-логике.

LocalTime lt = zdt.toLocalTime() ;  // Extract just the time-of-day as seen in the wall-clock time used by the people of this region (this time zone).

В качестве ярлыка вы можете вызвать LocalTime.now:

LocalTime lt = LocalTime.now( zKabul ) ;

Иранское время

Позже вВ наших комментариях вы поясните, что предполагаемый часовой пояс составляет Asia/Tehran, время в Иране .В настоящее время Иран соблюдает переход на летнее время (DST), что может стать причиной вашей путаницы.При стандартном смещении, если +03: 30 (за три с половиной часа до UTC), в период с 22 марта по 22 сентября смещение составляет +04: 30, еще на один час впереди по UTC.

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

Давайте создадим дату-время для 1 июня с вашим примером времени 4:55 в UTC.Мы можем использовать константу ZoneOffset.UTC.При использовании просто смещения от UTC (смещение нуля в данном случае), используйте OffsetDateTime. смещение от UTC - это просто количество часов и минут, ни больше, ни меньше.Напротив, часовой пояс - это история прошлых, настоящих и будущих изменений в смещении, используемом людьми определенного региона.

LocalTime lt = LocalTime.parse( "04:55" ) ;
LocalDate ld = LocalDate.of( 2018 , Month.JUNE , 1 ) ;
OffsetDateTime odt = OffsetDateTime.of( ld , lt , ZoneOffset.UTC ) ;

odt.toString (): 2018-06-01T04: 55Z

Настройтесь на зону Asia/Tehran, применив ZoneId, чтобы получитьZonedDateTime.Тот же момент, та же точка на временной шкале, но другое время на настенных часах.

ZoneId zTehran = ZoneId.of( "Asia/Tehran" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( zTehran );

zdt.toString (): 2018-06-01T09: 25 + 04: 30 [Азия / Тегеран]

Обратите внимание, что время дня летом показывает 9 часов, а не 8.

Попробуйте использовать тот же код с январским месяцем, когда летнее время равно не в силе.

LocalTime lt = LocalTime.parse( "04:55" );
LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 1 );
OffsetDateTime odt = OffsetDateTime.of( ld , lt , ZoneOffset.UTC );
ZoneId zTehran = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = odt.atZoneSameInstant( zTehran );

zdt.toString (): 2018-01-01T08: 25 + 03: 30 [Азия / Тегеран]

Теперь мысм. час 8.

Имена зон

Укажите правильное имя часового пояса в формате continent/region, например, America/Montreal, Africa/Casablanca или Pacific/Auckland.Никогда не используйте 3-4-буквенное сокращение, такое как EST или IST, поскольку они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).

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

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

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

О 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?

  • Java SE 8 , Java SE 9 , Java SE 10, а позже
    • Встроенный.
    • Часть стандартного Java API с встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функций java.time перенесена на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии Android связывают реализации классов java.time.
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянутое выше).См. Как использовать ThreeTenABP… .

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

0 голосов
/ 02 июня 2018

Попробуйте использовать метод ниже:

  private String convertDateToUserTimeZone(String serverDate) {
    String ourdate;

    try {
        SimpleDateFormat serverFormatter = new SimpleDateFormat(
                "yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.UK);
        serverFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date value = serverFormatter.parse(serverDate);
        TimeZone timeZone = TimeZone.getTimeZone("Asia/Kolkata");
//            SimpleDateFormat dateFormatter = new SimpleDateFormat(serverdateFormat, Locale.UK); //this format changeable
            serverFormatter.setTimeZone(timeZone);
            ourdate = serverFormatter.format(value);

        //Log.d("OurDate", OurDate);
    } catch (Exception e) {
        ourdate = "00-00-0000 00:00";
    }
    return ourdate;
}

Все поддерживаемые Android часовые пояса Часовой пояс Android

Я бы предложил JodaTime Lib для даты и времени.имеют богатые полезные функции.

0 голосов
/ 02 июня 2018

Попробуйте этот метод

public static String convertUTCtoLocalTimeZone(String date, String date_formate) {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(date_formate,Locale.getDefault());
    Date myDate = null;
    try {
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        myDate = simpleDateFormat.parse(date);
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return new SimpleDateFormat(date_formate, Locale.getDefault()).format(myDate); // Note: Use new DateFormat
}
0 голосов
/ 02 июня 2018
 df.setTimeZone(TimeZone.getDefault());

до

 df.setTimeZone(TimeZone.getTimeZone("GMT+4:30"));

рабочий код

String dateStr = "04:55";
                SimpleDateFormat df = new SimpleDateFormat("HH:mm");
                df.setTimeZone(TimeZone.getTimeZone("UTC"));
                Date date = null;
                try {
                    date = df.parse(dateStr);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                df.setTimeZone(TimeZone.getTimeZone("GMT+4:30"));
                String formattedDate = df.format(date);


                System.out.println(formattedDate);
                //time.setText(String.valueOf(formattedDate));

        }

вывод, который я получил 9: 25

...