Android 将utc转换为伊朗当地时间

Android 将utc转换为伊朗当地时间,android,timezone,simpledateformat,Android,Timezone,Simpledateformat,我尝试将UTC时间转换为本地时间,分钟工作正常,但小时总是比1小时晚,例如,如果UTC时间是04:55,我的电话时钟是9:25,但我的代码生成8:25 String dateStr = "04:55"; SimpleDateFormat df = new SimpleDateFormat("HH:mm"); df.setTimeZone(TimeZone.getTimeZone("UTC"));

我尝试将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));

工作代码

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的时区

我建议使用日期时间。它有很多有用的功能。

试试这个方法

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年伊朗没有DST 2018年夏天,伊朗的时区是亚洲/德黑兰,但在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[亚洲/德黑兰]

但我怀疑您的代码在解析字符串1970-01-01T00:00:00Z时默认为UTC中1970年第一个时刻的日期,因为您正在滥用该类,试图解析一天中的某个时间而不指定日期

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[亚洲/德黑兰]

错班 您使用了错误的类

您希望表示一天中的某个时间值。所以你应该使用一天中的一节课。但是您使用的是一个日期和时间类,
java.util.date

ZoneId zKabul = ZoneId.of( "Asia/Kabul" ) ;
ZonedDateTime zdt = instant.atZone( zKabul ) ;
您正在使用设计糟糕的日期时间类,
java.util.date
&
java.text.simpleDataFormat
。多年前,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.
)
String input = "04:55" ;
LocalTime lt = LocalTime.parse( input ) ;
或者指定一个特定的时区

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
对象。此类表示一天中没有日期和时区的时间

LocalTime.now(
    ZoneId.systemDefault()       // Capture the current time of day by explicitly asking for the JVM’s current default time zone.
)
String input = "04:55" ;
LocalTime lt = LocalTime.parse( input ) ;
术语 我尝试将UTC时间转换为当地时间

您的短语“本地时间”在日期时间处理中有特定的含义。不幸的是,这个意思与你的意图相反。在*java.time.local…“类中看到的“local”一词是指任何地方或所有地方,而不是任何一个特定的地方

因此,一个
LocalTime
对象只有附加到一个日期并放在一个时区(或UTC的偏移量)的上下文中,才具有真正的意义

时区 如果UTC时间是04:55,我的手机时钟是9:25

这意味着您的JVM当前的默认时区使用UTC的偏移量,比UTC提前四个半小时,
+04:30
。根据此as,当前只有一个时区使用该偏移量:

要完全表示当前时刻,您需要一个日期和时间以及区域/偏移。要捕获当前时刻,请使用
Instant
。该类表示时间线上的一个时刻,分辨率为(小数点的九(9)位)

要查看时区中的同一时刻,请应用
ZoneId
以获取
zoneDateTime

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).
作为快捷方式,您可以调用:

伊朗时间 在后面的评论中,您解释了您的预期时区是
亚洲/德黑兰
。目前,伊朗遵守夏时制(DST),这可能是你困惑的根源。标准偏移量为+03:30(比UTC提前三个半小时),而3月22日至9月22日之间的偏移量为+04:30,比UTC提前一个多小时

这正是您应该指定所需/预期时区的原因。对于临时使用,可以使用JVM的当前默认时区。但要知道,默认值可以在运行时的任何时刻更改。违约可能不是你想要的。对于关键用途,始终与用户确认其预期时区

LocalTime.now(
    ZoneId.systemDefault()       // Capture the current time of day by explicitly asking for the JVM’s current default time zone.
)
String input = "04:55" ;
LocalTime lt = LocalTime.parse( input ) ;
让我们用您的示例时间UTC中的4:55建立6月1日的日期时间。我们可以使用常数。当仅使用UTC的偏移量(本例中为零的偏移量)时,使用。一个时间仅仅是一个小时和分钟数,不多也不少。相反,a是特定地区人民使用的补偿的过去、现在和未来变化的历史

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
获得
zoneDateTime
来调整到区域
Asia/Tehran
。同一时刻,时间线上的同一点,但墙上的时钟时间不同

ZoneId zTehran = ZoneId.of( "Asia/Tehran" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( zTehran );
zdt.toString():2018-06-01T09:25+04:30[亚洲/德黑兰]

请注意,夏季一天的时间显示为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[亚洲/德黑兰]

现在我们看到一小时8点

区域名称 以
大陆/地区
的格式指定,例如,或
太平洋/奥克兰
。切勿使用3-4个字母的缩写,如
EST
IST
,因为它们不是真正的时区,也不是标准化的,甚至不是唯一的(!)

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

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

关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类