Possible underflow error through the usage of java.util.Date - java

This code:
package test;
import java.util.Date;
public class DateUnderflow {
public static void main(String[] args) {
Long timestamp = -8120649749785140250L;
System.out.println(new Date(timestamp));
}
}
Produces the following output:
"Sat Aug 03 10:00:59 CET 257325894"
How come? An underflow without an exception?
Doc says says the date parameter of Date(long date) is the number of milliseconds since epoch, so I'm a bit surprised to find myself that far into the future..
My setup:
Linux mint 17.1
Eclipse Luna Service Release 1a (4.4.1)
java7-openjdk-amd64

RTFM (manual)
public Date(long date)
Constructs a Date object using the given
milliseconds time value. If the given milliseconds value contains time
information, the driver will set the time components to the time in
the default time zone (the time zone of the Java virtual machine
running the application) that corresponds to zero GMT.
Parameters:
date - milliseconds since January 1, 1970, 00:00:00 GMT not to exceed
the milliseconds representation for the year 8099. A negative number
indicates the number of milliseconds before January 1, 1970, 00:00:00
GMT.
not to exceed the milliseconds representation for the year 8099
In addition to this I am most likely saving someones time by saying: if you deal with time in java use joda time library:
http://www.joda.org/joda-time/

Max long value is 9223372036854775807. If you exceeds this max value, next value would be minimum max value.
If you construct a date out of this max long value, this will results to a date. What about a date next to that. If you add more mili-second to the next starts from minimum long value.
-8120649749785140250 is equivalent to 9223372036854775807 + 1102722287069635559
Try System.out.println(9223372036854775807L+1102722287069635559L);
I believe your code is equivalent to
Date d1 = new Date(9223372036854775807L); // Date for max long value
Date d2 = new Date(d1.getTime() + 1102722287069635559L); // plus some mili-seconds
System.out.println(d2);
This gives the result you are getting.

Related

Java Convert long value to date with exact precision of nano seconds

The date in database is 2012-03-20 12:24:34.123456. We need to display it in long format.so, we used getTime() method. But when we are converting back to date again, the nano seconds are not matching exact precision. The date after conversion is 2012-03-20 12:24:34.123. last 456 is missing. any one help to get exact date with nano seconds.
From javadoc
java.util.Date, getTime(), returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object. 456 is missing because is less than millisecond, is microseconds
You can use getTimestamp() instead of getTime(). The java.sql.Timestamp object returned, when treated like a java.util.Date, has integer seconds. By calling getNanos() on it, you can get the fractional seconds in nanoseconds.

Java time problems

I have a problem of inconsistency with time objects
Time time1 = new Time(72000000); //21:00
Time time2 = new Time(new Date().getTime()); //before 21 pm
time2.before(time1);
The last line returns always false, why?
Time:
A thin wrapper around the java.util.Date class that allows the JDBC API to identify this as an SQL TIME value. The Time class adds formatting and parsing operations to support the JDBC escape syntax for time values.
The date components should be set to the "zero epoch" value of January 1, 1970 and should not be accessed.
http://docs.oracle.com/javase/7/docs/api/java/sql/Time.html
Basically you're comparing 21:00 at the first of january 1970 to your current date at some point in the day. Obviously the former time happens earlier and is 'smaller'.
This is not doing what you think it's supposed to do!
Time time1 = new Time(72000000);
See this:
Time
public Time(long time)
Constructs a Time object using a milliseconds time value.
Parameters:
time - milliseconds since January 1, 1970, 00:00:00 GMT; a negative number is milliseconds before January 1, 1970, 00:00:00 GMT
Now, hopefully you understand...
Since you didn't specify otherwise, I assume that the Time object is java.sql.Time.
This object uses a superclass of java.util.Date so it is actually a full date object. For the purposes of JDBC (SQL) it only concerns itself with the time portion of the date.
This:
Time time1 = new Time(72000000);
...creates an object that represents 1-January-1970 21:00 hours. It will always be before any current time.
Seems that time1 is 14:00 . Run the below code snippet.
Time time1 = new Time(72000000); //21:00
System.out.println(time1); //prints 14:00
System.out.println(new Date());
Time time2 = new Time(new Date().getTime()); //before 21 pm

java.util.Date get milliseconds

I have done the following:
String standardRange = "00:01:01";
SimpleDateFormat rangeFormatter = new SimpleDateFormat("hh:mm:ss");
Date range = rangeFormatter.parse(standardRange);
Now:
range.getTime();
.. I get the output of -3539000 and not 61,000
I'm not sure what I'm doing wrong; when debugging, cdate exists, the attribute contains a fraction, which contains the value 61,000, which is what I want.
The reason you're seeing this is that the date you're creating is actually in the past of the date epoch, not 1m1s after it:
String standartRange = "00:01:01";
SimpleDateFormat rangeFormatter = new SimpleDateFormat("hh:mm:ss");
Date range = rangeFormatter.parse(standartRange);
System.out.println(new Date(0L));
System.out.println(new Date(0L).getTime());
System.out.println(range);
System.out.println(range.getTime());
and its output;
Thu Jan 01 01:00:00 GMT 1970
0
Thu Jan 01 00:01:01 GMT 1970
-3539000
The epoch date is incorrect here - it should be 00:00:00, but due to a historical bug where BST/GMT changed dates and timezone cant keep track. It seems that Sun/Oracle consider this a historical "inaccuracy".
Check out the bug report - its describes the problem more fully.
From your language (German) this may not be directly due to this BST issue, but its almost certainly related.
Java Date is not designed to calculate the duration of a given time period.
The getTime() call returns the numbers of milliseconds since January 1, 1970, 00:00:00 GMT. In your case you are actually ending up with a date that comes before that epoch (thus the negative number). When I run your code I get 21661000. (See the answer from Sean Landsman as I believe he has hit on why you get the negative results...hint: my number is exactly 6 hours off of GMT or 21600000ms)
Joda-Time is a library that is well suited to solving your underlying problem.
PeriodFormatter formatter = new PeriodFormatterBuilder()
.appendHours()
.appendSeparator(":")
.appendMinutes()
.appendSeparator(":")
.appendSeconds()
.toFormatter();
Period period = formatter.parsePeriod("00:01:01");
assert period.toStandardDuration().getMillis() == 61000
According to the JavaDoc, getTime():
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.
You want the number of milliseconds in one minute and one second.
(60*minutes+seconds)*1000
It really doesn't need to come from a Date object.
If you need to compute the time in milliseconds for some interval, maybe use the joda time library, or get the day, hour, minute, second and millisecond components out of your date object and compute the value by hand.
To get what you want, you should compare between the time you want and origin of the time. using the below code:
String standardRange = "00:01:01";
SimpleDateFormat rangeFormatter = new SimpleDateFormat("HH:mm:ss");
Date range = rangeFormatter.parse(standardRange);
Date range2 = rangeFormatter.parse("00:00:00");
System.out.println(range.getTime() - range2.getTime());
hh:mm:ss stands for 12-hour time, which always stands for "time point", not "time interval". So surely, time zone will effect the value. However, in GMT +0 the value equals to which represents "time interval".
All you just need is:
rangeFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
Try it!
Try:
Date range1 = rangeFormatter.parse("00:01:01");
Date range2 = rangeFormatter.parse("00:00:00");
System.out.println(range1.getTime() - range2.getTime());

Algorithm of Java Date getTime

How does java.util.Date.getTime method convert a given date & time into long number?
Java API documents say that - "Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object."
Appreciate any help.
Check out the Date.java source code.
You'll see that in the simplest case, the Date object stores the number of milliseconds since 1970, rather than the date/time etc.
Actually, despite the apparently unambiguous definition in the Java API doc, it is interesting to note that the number of milliseconds reported is not the actual number of physical milliseconds, or seconds for that matter, that have elapsed since January 1st 1970 00:00:00 GMT. It is really the number of physical seconds plus the number of leap seconds that have been artificially inserted.

How to retrieve milliseconds from java.sql.Timestamp

I have a timestamp object and need to get the milliseconds from it, can someone help me with an example code snippet ?
You can use Timestamp.getTime()
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
represented by this Timestamp object.
Example:
long timeInMilliSeconds = t.getTime();
// do magic trick here
Note: Timestamp is extend from Date.
You can just call getTime() to get milliseconds since the Unix epoch. Is that what you were after, or did you want "milliseconds within the second" or something similar?
Note that using just milliseconds is slightly odd for a Timestamp, given that it's designed specifically to be precise to the nanosecond. So you should usually be using getTime() in conjunction with getNanos().
From the Java Docu (link):
public long getTime()
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Timestamp object.
I guess this will give the output you want.
public void timeInMills(Timestamp t){
System.out.println("Time in Milli second "+t.getTime());
}

Categories