将 UTC 时间转换为伊朗本地时间

convert utc to local time in iran

我尝试将 UTC 时间转换为当地时间,分钟工作正常但小时总是晚 1 小时,例如,如果 UTC 时间是 04:55,我的 phone 时钟是 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));
 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

试试下面的方法:

  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 Timezone

我建议 JodaTime Lib for Date time.Its 具有丰富有用的功能。

试试这个方法

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
}

1970 年伊朗没有夏令时

伊朗 Asia/Tehran 的时区在 2018 年夏季观察到 Daylight Saving Time (DST),但在 1970 年没有观察到。

2018 年夏天,伊朗比 UTC 时间早四个半小时,而不是三个半小时。因此,从 UTC 中的 4:55 进行调整应该会在夏日导致 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[Asia/Tehran]

但我怀疑您的代码在解析您的字符串 1970-01-01T00:00:00Z 时默认为 UTC 1970 年第一时刻的 epoch reference 日期,因为您滥用了 class 尝试在不指定日期的情况下解析时间。

1970 年,伊朗没有遵守夏令时 (DST)。因此,偏移量比 1970 年夏天的 UTC 时间提前三个半小时,而 2018 年夏天的时间偏移量比 UTC 时间提前四个半小时。

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

1970-01-01T08:25+03:30[Asia/Tehran]

错误class是

您使用了错误的 classes。

您想表示一天中的时间值。所以你应该使用一天中的时间 class。但是您使用的是日期和时间 class、java.util.Date

您正在使用麻烦的设计糟糕的日期时间 classes,java.util.Date & java.text.SimpleDateFormat。这些在几年前被 java.time classes 所取代。完全避免遗留 classes。仅使用在 java.time package.

中找到的 classes

一天中的时间

解析时间字符串。

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 对象。 class 表示没有日期和时区的时间。

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

术语

I try convert UTC time to local time

您的短语“本地时间”在日期时间处理中具有特定含义。不幸的是,这个意思与您的意图相反。在 *java.time.Local... 中看到的“本地”一词 classes 表示 any locality 或 all地方而不是任何一个特定的地方。

所以 LocalTime 对象在附加到日期并放置在时区(或与 UTC 的偏移量)的上下文中之前没有真正的意义。

时区

if UTC time is 04:55 , my phone clock is 9:25

这意味着您的 JVM 当前默认时区正在使用比 UTC 提前四个半小时的 UTC 偏移量,+04:30。据此list of time zones as managed by the IANA, there are only one time zone currently using that offset: Asia/Kabul

要完整表示当前时刻,您需要日期和时间以及 zone/offset。要捕捉当前时刻,请使用 InstantInstant class represents a moment on the timeline in UTC with a resolution of nanoseconds(最多九 (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/Tehrantime in Iran。目前,伊朗实行夏令时 (DST),这可能是您困惑的根源。虽然标准偏移量为 +03:30(比 UTC 早三个半小时),但在 3 月 22 日至 9 月 22 日之间,偏移量为 +04:30,比 UTC 早一小时。

这正是您应该指定 desired/expected 时区的原因。对于临时使用,您可以使用 JVM 当前的默认时区。但要知道默认值可以在运行时随时更改。并且默认值可能不是您想要的。对于关键用途,请始终与用户确认他们的预期时区。

让我们使用 UTC 中的示例时间 4:55 建立 6 月 1 日的日期时间。我们可以使用常数 ZoneOffset.UTC. When using merely an offset-from-UTC (an offset of zero in this case), use OffsetDateTime. An offset-from-UTC is merely a number of hours and minutes, nothing more, nothing less. In contrast, a time zone 是特定区域的人们使用的偏移量的过去、现在和未来变化的历史。

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

通过应用 ZoneId 获得 ZonedDateTime 调整到区间 Asia/Tehran。同一时刻,时间轴上的同一点,但挂钟时间不同。

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

zdt.toString(): 2018-06-01T09:25+04:30[Asia/Tehran]

请注意夏季的时间显示为 9 小时,而不是 8 小时。

在 DST 生效时,尝试使用与 1 月份相同的代码。

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[Asia/Tehran]

现在我们看到一个小时是 8。

区域名称

指定一个proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca,或Pacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们 不是 真正的时区,没有标准化,甚至不是唯一的(!)。

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

如果你想使用 JVM 当前的默认时区,请求它并作为参数传递。如果省略,则隐式应用 JVM 的当前默认值。最好是显式的,因为默认值可能会在任何时候 在运行时 中被 JVM 中任何应用程序的任何线程中的任何代码更改。

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

关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与您的数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

从哪里获得java.time classes?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.