Why SimpleDateFormat.parse (). Does getTime () return an incorrect (negative) value?

I have a timestamp of type String, and I'm trying to convert it to double (and find the result in seconds), and here is what I did:

double mytimeStamp = 0; String timeStamp = new SimpleDateFormat(" mm ss S").format(new Date( )); SimpleDateFormat dateFormat = new SimpleDateFormat(" mm ss S"); try { mytimeStamp = ((double)dateFormat.parse(timeStamp).getTime())/1000; } catch (ParseException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } System.out.println("timeStamp is: "+ mytimeStamp); 

The problem is that I get a value such as -2722.515 and I don't know why.

Why is this negative?

Is there something wrong with the code?

When I convert this time stamp to mm ss S , it does not correspond to real time, and this seems to be another problem!

+7
source share
2 answers

This is a time zone mismatch problem.

Since you specified only the minute and second, the date will be on 1 Jan 1970 00:mm:ss ( mm and ss ), as minutes and seconds of the current time).

I simplified your example:

 String timeStamp = "00 00 00"; SimpleDateFormat dateFormat = new SimpleDateFormat("HH mm ss"); double hour = dateFormat.parse(timeStamp).getTime()/1000.0/60/60; System.out.println("hour is: "+ hour); 

The printed hour must be GMT offset from the local time zone.

The reason of that:

SimpleDateFormat locale sensitive, so dateFormat.parse(timeStamp) will return the creation of a Date object for the given time zone (the default is the local time zone). getTime() gets the number of milliseconds from midnight 1 Jan 1970 **GMT** . Thus, the value will be compensated by how much the local time zone is from GMT .

How to fix it:

You can fix this by setting the time zone of the dateFormat object before calling parse as follows:

 dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); 
+11
source

--- Actually there is a much better way to do this, but if you want to use dates, skip the preliminary answer ---

Dates do not actually do what you want, which is apparently a calculation of time beyond the actual need to select time from the real world.

It will be much better for you to write your own class to avoid any unpleasant special treatment that the Dates must do to keep up with the Gregorian calendar. This special processing includes (but is not limited to) time zone information, daylight saving time, announced "missed days", leap seconds, leap years, etc.

 public TimeOnly { private long timestamp; private int millis; private int seconds; ... etc ... public TimeOnly(int hours, int minutes, int seconds, int millis) { this.timestamp = millis + seconds * 1000L + minutes * 60000L + hours * 3600000L; this.millis = millis; this.seconds = seconds; ... etc ... } private TimeOnly(long timestamp) { this.timestamp = timestamp; this.millis = timestamp % 1000; this.seconds = timestamp % 60000L - this.millis; ... etc ... } public long getTimestamp() { return timestamp; } public int getMillis() { return millis; } public int getSeconds() { return seconds; } ... etc ... } public TimeFormatter { public TimeFormatter() { } public String format(Time time) { StringBuilder builder = new StringBuilder(); builder.append(String.valueOf(time.getHours())); builder.append(":"); builder.append(String.valueOf(time.getMinutes())); builder.append(":"); builder.append(String.valueOf(time.getSeconds())); builder.append("."); if (time.getMillis() < 10) { builder.append("00"); } else if (time.getMillis() < 100) { builder.append("0"); } builder.append(time.getMillis()); return builder.toString(); } 

This decision may seem like he was inventing a wheel, but in fact he is avoiding using an octagon as a wheel. The behavior of the date is not what you want, although you could make Date work for some limited range of values.

If you want to get really fantasy, you could make the above tool comparable, etc. However, I would advise you not to do it. Do not provide update methods after the build, as this leads to some rather unpleasant recalculations and makes the code more difficult to maintain. Instead, provide methods that return new TimeOnlys in response to the operations you want to implement.

 public TimeOnly addSeconds(int value) { int stamp = this.timestamp; stamp += value * 60000L; if (stamp < timestamp) { throw new Excepton("overflow"); } return new TimeOnly(stamp); } 

Also, do not implement what you are not going to use. Unused code tends to be fertile ground for errors.

And, of course, a fallback for all โ€œtemporaryโ€ things, consider using JodaTime, which distinguishes all of the different types of time measurements. However, for this small problem, it is similar to using a tank to destroy ant.

--- Preliminary answer ---

Without a full time specification (year, month, day, hour, minute, second, milliseconds), your time value formatted in the first step will have many fields that are not specified. What happens in these fields is likely to be garbage.

getTime() acts on the entire Date object, translating both valid fields and garbage into a value, where garbage can even change valid values โ€‹โ€‹(96 sec = 1 minute and 36 seconds when the fields interact).

The best way to do this is to have all your โ€œonly timeโ€ dates initialized to one known day, so when you perform comparisons and mathematical operations (is it, 3 11 23 > 1 02 10 ?), You get consistent results (yes, 3 11 23 > 1 02 10 , because actually it is 2013 02 10 00 03 11 23 > 2013 02 10 00 03 11 23 and not 2013 02 10 00 03 11 23 compared with 2000 02 10 00 03 11 23

When choosing a day to use, avoid the days adjacent to February 29, days that are approaching daylight saving time, etc.

+1
source

All Articles