我尝试将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));
答案 0 :(得分:3)
伊朗的时区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 [亚/德黑兰]
但我怀疑你的代码在解析你的字符串1970-01-01T00:00:00Z时默认为1970年第一时间的epoch reference日期,因为你在试图解析时滥用该类没有指定日期的时间。
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
。
您正在使用设计糟糕的日期时间类java.util.Date
& java.text.SimpleDateFormat
。几年前, java.time 类取代了这些。完全避免遗留类。仅使用java.time package中的类。
解析时间字符串。
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
)
4时55分
LocalTime
如果您有输入字符串,例如" 04:55",则解析为LocalTime
对象。此类表示没有日期且没有时区的时间。
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
。根据此list of time zones managed by the IANA,目前只有一个时区使用该偏移:Asia/Kabul
。
要完全表示当前时刻,您需要一个日期和时间以及区域/偏移。要捕获当前时刻,请使用Instant
。 Instant
类代表UTC中时间轴上的一个时刻,分辨率为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/Tehran
,time in Iran。目前,伊朗观察夏令时(DST),这可能是您混淆的根源。如果标准偏移为+ 03:30(比UTC早三个半小时),则在3月22日到9月22日之间,偏移量为+04:30,比UTC早一个小时。
这正是您应该指定所需/预期时区的原因。对于临时使用,您可以使用JVM的当前默认时区。但是要知道默认值可以在运行时随时改变。默认可能不是你想要的。对于关键用途,请始终与用户确认其预期的时区。
让我们在6月1日建立一个日期时间,你的示例时间是UTC时间4:55。我们可以使用常量ZoneOffset.UTC
。如果仅使用UTC的偏移量(在这种情况下偏移量为零),请使用OffsetDateTime
。 offset-from-UTC仅仅是几小时和几分钟,仅此而已。相比之下,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
通过应用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小时。
在1月份使用相同的代码,当DST 无效时。
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
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用诸如EST
或IST
之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
如果要使用JVM的当前默认时区,请求它并作为参数传递。如果省略,则隐式应用JVM的当前默认值。最好是明确的,因为默认情况下可以在运行时期间由JVM中任何应用程序的任何线程中的任何代码随时更改。
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 1 :(得分:2)
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
答案 2 :(得分:1)
尝试以下方法:
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。它具有丰富的实用功能。
答案 3 :(得分:1)
试试这个方法
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
}