将日期字符串解析为Date并将其转换为millis后,输出时间总是在两小时内降低

时间:2018-01-10 12:23:47

标签: java android date datetime

我正在尝试将带有日期的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转换回来后如何才能获得有效的结果?为什么我会在两小时内得到这个差异?

4 个答案:

答案 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等价物。)

问题:我可以在Android上使用java.time吗?

你当然可以(我自己没有经验)。

  • 对于一般的Android市场,请使用Android版的ThreeTen Backport(如下所述)。它被称为ThreeTenABP。然后导入org.threeten.bp.format.DateTimeFormatterorg.threeten.bp.LocalDateTime
  • 对于使用Java 8的较新的Android设备,如果您导入java.time.format.DateTimeFormatterjava.time.LocalDateTime,它应该可以开箱即用。

在非Android Java上?

  • 在Java 8及更高版本中,内置了新的API。
  • 在Java 6和7中获取ThreeTen Backport,这是新类的后端(JST 310的ThreeTen)。

链接

答案 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());

    }

}