Java 将日期字符串解析为日期并将其转换为毫秒后,输出时间总是低于两小时

Java 将日期字符串解析为日期并将其转换为毫秒后,输出时间总是低于两小时,java,android,date,datetime,Java,Android,Date,Datetime,我试图将带有日期的字符串解析为日期对象,然后将其转换为毫秒 但无论我在做什么,输出结果(毫秒)总是比输入日期在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(d

我试图将带有日期的
字符串
解析为
日期
对象,然后将其转换为毫秒

但无论我在做什么,输出结果(毫秒)总是比输入日期在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

我无法理解为什么会发生这种情况。如何在转换毫秒后返回有效结果?为什么我在两个小时内得到这个差异?

通过解析字符串,可以假定给定的时间基于您的本地时间,而日期是UTC。如果未指定时区,SimpleDataFormat将使用PC时区为您进行转换

要将其转换回,应使用
新日期(毫秒)

这也考虑了您的时区,您的结果应该是正确的。

这看起来像是时区问题

检查您所在的时区。如果您在UTC+02:00,结果很好

如果要手动设置时区以与UTC相匹配(无偏移),请选中此堆栈溢出问题:


我希望这能对您有所帮助:)

又一个例子,说明现代java日期和时间API
java.time
的优越之处。它强制您为此类操作指定区域偏移或时区,从而解决了问题:

    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(可能更容易阅读为1515583800000)。删除要转换为秒的最后三个零,然后输入它们,例如。结果是:

2018年1月10日星期三11:30:00 GMT

<> P GMT最后确认时间在预期偏移(现在我们可以考虑GMT和UTC等效)。 问题:我可以在Android上使用
java.time
? 你当然可以(不过我自己还没有这方面的经验)

  • 对于一般的Android市场,使用Android版本的ThreeTen Backport(如下所述)。它叫ThreeTenABP。然后导入
    org.threeten.bp.format.DateTimeFormatter
    org.threeten.bp.LocalDateTime
  • 对于使用Java 8的较新Android设备,如果导入
    Java.time.format.DateTimeFormatter
    Java.time.LocalDateTime
    ,它应该可以开箱即用
以及在非Android Java上?

  • 在Java8和更高版本中,新的API是内置的
  • 在Java6和Java7中,获取三个后端口,即新类的后端口(三个用于JSR310)
链接
  • ,解释如何使用
    java.time
  • ,Android版Three Ten Backport
  • ,解释得非常透彻
  • ,其中首次描述了现代日期和时间API

我想您现在已经意识到这是一个时区问题,但我想我会为您提供一个助手类,我编写并在大多数应用程序中使用该类,因为客户机-服务器应用程序始终必须考虑时区,并且应该在服务器上存储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());

    }

}
希望这对您有所帮助,您可以复制和粘贴这个类,并在服务器之间处理许多日期格式和时区问题

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

    }

}

这看起来像是时区问题。您在哪个时区?请提供您的代码和更多详细信息。我得到了正确的输出。此外,毫秒的值为1515564000000,这与您得到的不同时区是至关重要的。您需要指定在哪个时区解释您的11:30。给我:格林尼治时间:2018年1月10日星期三上午9:30:00。您的时区:2018年1月10日星期三上午10:30:00 GMT+01:00。如果你的11:30在区域偏移UTC+02:00,结果与它一致。作为一个旁白,考虑扔掉长期过时和臭名昭著的麻烦<代码> SimpleDateFormat <代码>和朋友,并添加到你的Android项目中,以便使用<代码> java.时间>代码>,java java日期和时间API。和我一起工作真是太好了。是的,我在UTC+02.00。对我来说,正确的时间是11点30分。但总是在把日期转换成毫秒后,我会得到9点30分。是否可以转换没有时区的日期以避免这些时间更改?只需按照我的答案中的链接“如何手动设置java.util.Date的时区?”即可获得问题的答案;-)谢谢,我会试试:-)谢谢你的帮助)在设置时区之后-如果最终得到结果谢谢,但是-DateTimeFormatter.of模式对我来说不是很合适,因为我的最小API级别是15((我不太确定,15级还不够,你可以使用,现代API(也称为JSR-310)的后端口)到Android?这里有更多:。在这种情况下,请确保从
org.threeten.bp
导入。向项目中添加threeten Backport和ThreetenABP库绝对值得。遗留日期-时间类是一个糟糕的烂摊子,应该避免。