我正在尝试将带有日期的String
解析为Date
对象,然后将其转换为毫秒。
但无论我做什么 - 以毫秒为单位的输出结果总是比输入日期低2小时。
例如,如果输入日期 2018-1-10 11:30 - 输出日期将为 2018-01-10 9:30 。
这是我的代码:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String dateString = "2018-1-10 11:30";
Date resultDate = sdf.parse(dateString);
long millis = resultDate.getTime();
// millis = 1515576600000
// When i am trying to convert millis to normal date via online
// converters i am always getting
// this result 10.01.18 9:30
我无法理解为什么会这样。将millis转换回来后如何才能获得有效的结果?为什么我会在两小时内得到这个差异?
答案 0 :(得分:1)
这看起来像是时区问题。
检查您所在的时区。如果您在 UTC +02:00 ,结果很好!
如果您想手动设置时区以匹配UTC(没有偏移),请检查此堆栈溢出问题:How to set time zone of a java.util.Date?
我希望这可以帮助你:)。
答案 1 :(得分:1)
另一个例子是java.time
,现代Java日期和时间API,擅长。它会强制您为此类操作指定区域偏移或时区,从而解决问题:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-M-d H:mm");
String dateString = "2018-1-10 11:30";
long epochMillis = LocalDateTime.parse(dateString, dtf)
.atOffset(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
结果是1515583800000(可能更具可读性为1 515 583 800 000)。删除最后三个零以转换为秒并输入它们,例如http://www.onlineconversion.com/unix_time.htm。结果是:
2018年1月10日星期三11:30:00 GMT
GMT最终确认时间是预期的偏差(现在我们可以考虑GMT和UTC等价物。)
java.time
吗?你当然可以(我自己没有经验)。
org.threeten.bp.format.DateTimeFormatter
和org.threeten.bp.LocalDateTime
。java.time.format.DateTimeFormatter
和java.time.LocalDateTime
,它应该可以开箱即用。在非Android Java上?
java.time
。答案 2 :(得分:0)
通过解析字符串,可以假定给定时间基于您的本地时间,而Date则是UTC。如果您没有指定,SimpleDateFormat会使用您的pc时区为您进行转换。
https://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html#setTimeZone(java.util.TimeZone)
https://docs.oracle.com/javase/8/docs/api/java/util/Date.html
要将其转换回来,您应该使用new Date (millis)
这也考虑了你的时区,你的结果应该是正确的。
答案 3 :(得分:0)
我想您现在知道这是一个时区问题,但我想我会为您提供一个帮助类,我在大多数应用程序中编写和使用,因为客户端服务器应用程序总是需要考虑帐户时区,应该是将GMT存储在服务器上。
希望这会有所帮助,您可以复制并粘贴此类,并在服务器之间处理大量日期格式和时区问题。
public class DateHelper {
/*///////////////////////////////////////////////////////////////
// MEMBERS
*////////////////////////////////////////////////////////////////
public static SimpleDateFormat MY_APPS_CUSTOM_FORMATTER;
public final static String MMMM_dd = "MMMM, dd";
public final static String MMM_dd_yyyy = "MMM dd yyyy";
public final static String MMSlashddSlashyy = "MM/dd/yy";
public final static String MMSlashddSlashyy_hhColonmm_a = "MM/dd/yy hh:mm a";
public final static Calendar mCalender = Calendar.getInstance();
public final static TimeZone mLocalTimezone = mCalender.getTimeZone();
/*///////////////////////////////////////////////////////////////
// PROPERTIES
*////////////////////////////////////////////////////////////////
public synchronized static SimpleDateFormat getMyAppsDateCustomFormatter(boolean toServer, String format){
MY_APPS_CUSTOM_FORMATTER = new SimpleDateFormat(format);
if(toServer){
MY_APPS_CUSTOM_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
}else{
MY_APPS_CUSTOM_FORMATTER.setTimeZone(mLocalTimezone);
}
return MY_APPS_CUSTOM_FORMATTER;
}
/*///////////////////////////////////////////////////////////////
// EXTRA HELPER METHODS
*////////////////////////////////////////////////////////////////
public static String getNowLocalTime(String formatToReturn){
return getMyAppsDateCustomFormatter(false, formatToReturn).format(new Date());
}
/*///////////////////////////////////////////////////////////////
// FROM SERVER FORMATTING
*////////////////////////////////////////////////////////////////
public static String getLocalDateStringFromGMTLong(long gmtTimestamp, String formatToReturn){
return getMyAppsDateCustomFormatter(false, formatToReturn).format(new Date(gmtTimestamp * 1000));
}
public static Date getDateFromLocalFormattedString(String date, String formatToUse, boolean toServer) throws Exception{
Date parsedDate = null;
try {
parsedDate = getMyAppsDateCustomFormatter(toServer, formatToUse).parse(date);
} catch (ParseException e) { //developer error, do NOT localize
throw new Exception(Globals.DEV_ERROR_STRINGS.INVALID_DATE_SUPPLIED_FOR_DEFAULT_FORMATTER);
}
return parsedDate;
}
public static String getFormattedStringFromLocalDate(Date date, String formatToUse) throws Exception{
return getMyAppsDateCustomFormatter(false, formatToUse).format(date);
}
/*///////////////////////////////////////////////////////////////
// TO SERVER FORMATTING
*////////////////////////////////////////////////////////////////
public static long getGMTLongFromLocalDate(Date date){
//Get Local Timezone
TimeZone tz = TimeZone.getDefault();
//Create new date for offset to GMT
Date ret = new Date(date.getTime() - tz.getRawOffset() );
// if we are now in DST, back off by the delta. Note that we are checking the GMT date, this is the KEY.
if ( tz.inDaylightTime( ret )){
Date dstDate = new Date( ret.getTime() - tz.getDSTSavings() );
// check to make sure we have not crossed back into standard time
// this happens when we are on the cusp of DST (7pm the day before the change for PDT)
if ( tz.inDaylightTime( dstDate )){
ret = dstDate;
}
}
return ret.getTime();
}
public static long getGMTLongFromLocalDateString(String date, String formatUsed) throws Exception {
Date passedDate = getDateFromLocalFormattedString(date, formatUsed, true);
//Get Local Timezone
TimeZone tz = TimeZone.getDefault();
//Create new date for offset to GMT
Date ret = new Date(passedDate.getTime() - tz.getRawOffset() );
// if we are now in DST, back off by the delta. Note that we are checking the GMT date, this is the KEY.
if ( tz.inDaylightTime( ret )){
Date dstDate = new Date( ret.getTime() - tz.getDSTSavings() );
// check to make sure we have not crossed back into standard time
// this happens when we are on the cusp of DST (7pm the day before the change for PDT)
if ( tz.inDaylightTime( dstDate )){
ret = dstDate;
}
}
return ret.getTime() / 1000;
}
public static long getNowGMTTime(){
return getGMTLongFromLocalDate(new Date());
}
}