将服务器日期转换为设备本地时间的功能:
public static String convertIntoLocalTime(String strTime, String whichTimeZone, String dateFormat) {
String strLocalTime = null;
try {
SimpleDateFormat sdf = getSimpleDateFormat(dateFormat, whichTimeZone);
Date date = sdf.parse(strTime);
AppLog.e(TAG,"Timezone = " + whichTimeZone);
AppLog.e(TAG,"Date = " + strTime);
AppLog.e(TAG,"Date in CET = " + date.toString());
AppLog.e(TAG,"inDaylightTime = " + sdf.getTimeZone().inDaylightTime(date));
AppLog.e(TAG,"DST savings = " + sdf.getTimeZone().getDSTSavings());
if (sdf.getTimeZone().getDSTSavings() == 3600000) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.HOUR, 1);
Date oneHourBack = cal.getTime();
SimpleDateFormat local = getLocalSimpleDateFormat(dateFormat);
strLocalTime = local.format(oneHourBack);
} else {
SimpleDateFormat local = getLocalSimpleDateFormat(dateFormat);
strLocalTime = local.format(date);
}
} catch (ParseException e) {
AppLog.e(TAG, e.getMessage(), e);
}
AppLog.e(TAG,"Local Time = " + strLocalTime);
return strLocalTime;
}
获取简单日期格式的功能:
private static SimpleDateFormat getSimpleDateFormat(String format, String tz) {
TimeZone timeZone = TimeZone.getTimeZone(tz);
timeZone.useDaylightTime();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, Locale.getDefault());
simpleDateFormat.setTimeZone(timeZone);
return simpleDateFormat;
}
获取本地设备转换的简单日期格式的功能:
/**
* @param format
* @return
*/
private static SimpleDateFormat getLocalSimpleDateFormat(String format) {
TimeZone timeZone = TimeZone.getDefault();
timeZone.useDaylightTime();
SimpleDateFormat localSdf = new SimpleDateFormat(format, Locale.getDefault());
localSdf.setTimeZone(timeZone);
return localSdf;
}
输出:
日期= 2018-04-22 14:30
CET日期=太阳4月22日13:30:00 GMT + 01:00 2018
inDaylightTime = true
DST节省= 3600000
当地时间= 2018-04-22 14:30
上面的代码在之前工作得非常好,例如我们在4月1日有一个正确显示时间的事件,但是从4月21日开始,它显示了额外的1小时时间。
我曾尝试使用UTC和CET转换来自服务器的日期,但在这两种情况下,当它转换为设备本地时间时,它会向我显示额外的一小时。
以上示例基于伦敦时区,而当我们在IST时区尝试时,它返回了正确的时间。
我们通过查看inDaylightTime
时区功能来处理DST时间不同,但它无效。
我确信有与DST有关的东西,但我无法弄清楚。谢谢你的帮助?
答案 0 :(得分:1)
首先,您使用的是旧的和过时的日期和时间类:SimpleDateFormat
,Date
,Calendar
和TimeZone
。这些都因设计糟糕而且有时候很麻烦而闻名。我的第一个建议是使用现代Java日期和时间API java.time
重写代码。它的错误要少得多,我希望您能更轻松地开发出正确的代码。
尽管如此,无论你是使用老式课还是现代课,都不要自己处理夏令时。图书馆课程将为您完成。你的工作是让时区正确。不要增加或减少一小时来弥补夏令时。看看有关从一个时区转换到另一个时区的其他问题,有很多。
请勿使用三个和四个字母的时区缩写。 CET不是时区。 IST含糊不清,可能意味着爱尔兰夏令时,以色列标准时间或印度标准时间。欧洲冬季使用CET的国家自2018年3月26日起使用CEST(中欧夏季时间)。
如果这是服务器时区,则将服务器时区指定为 continent / city ,例如Europe/London
。这是毫不含糊的。
还要确保将设备时区设置为真正的时区。看来你已经将它设置为GMT + 01:00,这是GMT偏移,而不是时区。它同意欧洲/伦敦时区和冬季的CET,但不是在3月26日之后。
最后,您向<{1}}添加 1小时,向前转1小时,然后拨打Calendar
从中获取Date
oneHourBack
。这看起来不错。你的意思是减去1小时,还是你的意思是变量应该是oneHourForward
?
编辑:我可能还没有确切地知道哪些时区对你来说是正确的,因此不是你的代码的正确输出。因此,请将以下内容仅作为您想要完成的内容的猜测。请填写正确的时区。
public static String convertIntoLocalTime(
String strTime, String serverTimeZone, String dateFormat) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat);
ZonedDateTime serverDateTime = LocalDateTime.parse(strTime, formatter)
.atZone(ZoneId.of(serverTimeZone));
AppLog.e(TAG, "Server timezone = " + serverTimeZone);
AppLog.e(TAG, "Date = " + strTime);
AppLog.e(TAG, "Date in server timezone = " + serverDateTime.toString());
ZonedDateTime deviceTime = serverDateTime
.withZoneSameInstant(ZoneId.systemDefault());
String strLocalTime = deviceTime.format(formatter);
AppLog.e(TAG, "Device Time = " + deviceTime);
AppLog.e(TAG, "Local Time = " + strLocalTime);
return strLocalTime;
}
我尝试将我的时区设置为欧洲/伦敦并发出以下呼叫:
convertIntoLocalTime("2018-04-22 14:30", "Europe/Berlin", "yyyy-MM-dd HH:mm")
我得到的输出是:
Server timezone = Europe/Berlin
Date = 2018-04-22 14:30
Date in server timezone = 2018-04-22T14:30+02:00[Europe/Berlin]
Device Time = 2018-04-22T13:30+01:00[Europe/London]
Local Time = 2018-04-22 13:30
是的,java.time
适用于较旧和较新的Android设备。它只需要至少Java 6 。
org.threeten.bp
导入日期和时间类。java.time
。java.time
。java.time
向Java 6和7的后端(JST-310的ThreeTen)。答案 1 :(得分:0)
我没有经过测试,所以先尝试一下。
public String convertIntoLocalTime(String strTime, String whichTimeZone, String dateFormat) {
String strLocalTime = null;
strLocalTime=convertDateToUserTimeZone(strTime,whichTimeZone,dateFormat);
return strLocalTime;
}
public String convertDateToUserTimeZone(String strTime, String whichTimeZone, String dateFormat) {
String ourdate;
try {
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat, Locale.UK);
formatter.setTimeZone(TimeZone.getTimeZone(whichTimeZone));
Date value = formatter.parse(strTime);
TimeZone timeZone = TimeZone.getTimeZone("Asia/Kolkata");
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat, Locale.UK); //this format changeable
dateFormatter.setTimeZone(timeZone);
ourdate = dateFormatter.format(value);
//Log.d("OurDate", OurDate);
} catch (Exception e) {
ourdate = "00-00-0000 00:00";
}
return ourdate;
}