SimpleDateFormat解析返回错误的值

时间:2013-10-22 10:32:48

标签: java parsing java-7 simpledateformat

我有这段代码:

public static String formatMinSecOrHourMinSec(final String length) {
        try {
            final SimpleDateFormat hhmmss = new SimpleDateFormat("HH:mm:ss", Locale.GERMAN);
            final Date date = hhmmss.parse(length);
            final GregorianCalendar gc0 = new GregorianCalendar(Locale.GERMAN);
            gc0.setTime(date);
            if(gc0.getTimeInMillis() >= 3600 * 1000){
                return hhmmss.format(gc0.getTime());
            }else{
                final SimpleDateFormat mmss = new SimpleDateFormat("mm:ss");
                return mmss.format(gc0.getTime());                    
            }
        } catch (final ParseException e) {
            LOGGER.debug("Konnte die Länge nicht parsen: " + length + "\n" + e);
            return length;
        }
    }

如果length设置为 01:29:00 ,我估计会返回 01:29:00 ,但会返回 29:00 即可。这是因为gc0.getTimeInMillis()比预期少了一小时(3600 * 1000)。我做错了什么?

2 个答案:

答案 0 :(得分:1)

这是因为java.util.Date正在使用您的默认时区。 (从date打印时间以毫秒为单位,您将看到)。 要修复它,请尝试:

final SimpleDateFormat hhmmss = new SimpleDateFormat("HH:mm:ss");
hhmmss.setTimeZone(TimeZone.getTimeZone("UTC"));

答案 1 :(得分:1)

tl; dr

请勿将时间跨度与时间混为一谈。两个不同的概念值得两个不同的类。时间范围由Duration(或Period)类表示。

Duration
.ofHours( 1 )
.plusMinutes( 29 ) 

…或…

Duration
.parse( "PT1H29M" ) 

错误的班级

首先,您正在使用不合适的类。显然,您正在尝试跟踪时间跨度,但使用的是时间。跨度和时间是两个不同的概念。两者混在一起会导致歧义,混乱和错误。

第二,您使用的是可怕的旧类,而这些老类在几年前被 java.time 类所取代。切勿使用SimpleDateFormatGregorianCalendar等。

时间跨度

在小时-分钟-秒范围内的时间跨度的正确类别是Duration。对于年月日范围,请使用Period

您可以从小时数和分钟数中实例化Duration

Duration d = Duration.ofHours( 1 ).plusMinutes( 29 ) ; 

或者您可以解析标准ISO 8601格式PnYnMnDTnHnMnS的字符串。

Duration d = Duration.parse( "PT1H29M" ) ;

日期时间

您可以使用日期时间值进行数学运算。也许您想知道从现在起一个小时零二十九分钟。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;  
ZonedDateTime now = ZonedDateTime.now( z ) ; // Capture the current moment as seen though the wall-clock time used by the people of some particular region.
ZonedDateTime later = now.plus( d ) ;  // Add a span-of-time to determine a later moment (or an earlier moment if the `Duration` is negative). 

关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance 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中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore