Java time problems - java

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

Related

offset current system time to time zone GMT in millisecs

I'm trying to modify the existing java code to output the data in milliseconds instead of seconds.
existing code which return current time in GMT in seconds:
currentTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
output currentTime = 1566311076
using epoch converter it says
GMT: Tuesday, August 20, 2019 2:24:36 PM
Your time zone: Tuesday, August 20, 2019 7:24:36 AM GMT-07:00 DST
My attempt to modify the java code to return current time in GMT in millisec is able to get current system time in millisec, however how do I offset the result to GMT time.
currentTime = ZonedDateTime.now().toInstant().toEpochMilli();
output currentTime = 1566336256566
Assuming that this timestamp is in milliseconds
GMT: Tuesday, August 20, 2019 9:24:16.566 PM
Your time zone: Tuesday, August 20, 2019 2:24:16.566 PM GMT-07:00 DST
do you know , will greatly appreaciate that. Thanks!
Convert to Instant first:
currentTime = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()
Demo
System.out.println(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC));
System.out.println(LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli());
Output
1566323773
1566323773363
Why do it in a more complicated way when a simple one exists?
long currentTime;
currentTime = System.currentTimeMillis();
System.out.println(currentTime);
Example output from just now:
1566369127348
I am a strong proponent of using the modern java.time classes including ZonedDateTime (maybe not so much LocalDateTime). However in this case a simple method from when Java was born gives us what we want. I see no issues with using it. If you do want to use java.time, use Instant:
currentTime = Instant.now().toEpochMilli();
System.out.println(currentTime);
1566369127348
What went wrong in your code?
Curiously your old code was incorrect. Your new attempt gives the correct number of milliseconds since the epoch. Your old code was:
currentTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
This takes the current wall-clock time in your time zone, or more precisely, in the default time zone of your JVM. It then incorrectly assumes that the time is in UTC and converts it to seconds since the epoch based on this assumption (of course, if the JVM’s time zone had been UTC, you would have happened to get the correct result).
I recommend you always pass a time zone (if not a clock) to a now method to make your expectations of the time zone used explicit. The no-arg now uses the JVM’s default time zone, which is unreliable because the setting can be changed unexpectedly, and may cause confusion. If the time zone had been stated in the above code line, we would all have been able to see at a glance whether it agreed with the UTC assumed afterward or not. The exception is Instant.now(): it doesn’t need a time zone since it gives the same result in all time zones.
Output from your old code on my computer in Europe/Copenhagen time zone was:
1566376327
You can see that it doesn’t agree with the millisecond values we got before (it’s two hours ahead in this case; in your case it was 7 hours behind).
Your question seems to have been posted some time around 10 PM (22:00) GMT (3 PM at offset -07:00), so none of your results fit well with that time. Either some hours went by from running your code to posting your question; or your computer clock is set incorrectly.

Get time difference java.sql.Time

I'm trying to get the time differente between two Time vars like this
long timeDiffLong = hFim.getTime() - hInic.getTime();
Time timeDiff = new Time(timeDiffLong);
The output is comming something like this
hFim = 17:30:00
hInic = 17:00:00
timeDiff = 20:30:00
instead of just showing 00:30:00 i always get 20h plus the result
If you use Java 8, you can do:
LocalTime from = hFim.toLocalTime();
LocalTime to = hInic.toLocalTime();
Duration d = Duration.between(from, to);
You can then query the hour/minute etc. with e.g. d.toMinutes().
By doing this
Time timeDiff = new Time(timeDiffLong);
you create a new time object, with timeDiffLong being the milliseconds since 1970-01-01 00:00 UTC. Since the difference is 30 minutes, the Time object will refer to 1970-01-01 00:30 UTC. But here comes the catch: timeDiff.toString() will output the time in the default time zone, that is, in most cases the time zone where you are currently are.
Long story short: Do not force an interval (duration, time difference) into a Time object. Either use a Duration class (Joda has one) or just do the division and modulo calculations yourself, as proposed by Kushan.
Looks like a duplicated question, have you seen already this answer?
How to find difference between two Joda-Time DateTimes in minutes
You should take a look at Joda time:
http://www.joda.org/joda-time/
Your problem is that when you create the time diff with
Time timeDiff = new Time(timeDiffLong);
and output that with System.out.println(timeDiff) then the result is shown for your local time zone. You can see that when you do this:
System.out.println(new Time(0));
TimeZone.setDefault(TimeZone.getTimeZone("PST"));
System.out.println(new Time(0));
That produces the following output here
00:00:00 //will probably be 20:00:00 for you
16:00:00
In short: Your time difference is shown as a GMT date converted to your local time zone and that is why its several hours off.

How to Get UTC DateTime

How can I get UTC DateTime from the following code? Right now with these lines of code, I get an output like this Fri Dec 31 05:30:00 IST 9999. Is this output is correct? I mean to say is this time is the UTC time. Any suggestions or help?
Code snapshot
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.set(9999, 11, 31, 0, 0, 0);
Date date = cal.getTime();
System.out.println(date);
Well, the output is correct in that it's what I'd expect for midnight UTC when you're running on a system in IST. Date.toString() always uses your system local time zone - because it doesn't have any other information. A Calendar knows its time zone, but a Date doesn't. The underlying information is just "the number of milliseconds since the Unix epoch".
If you want to convert a Date to a textual representation in a particular time zone, use SimpleDateFormat and specify the time zone there.
The problem here is that you're using the Date.toString() method that returns the local time zone.
You can use this code to get the current time in UTC:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
And then just use that object to get the time you want and use it, do note that cal.getTimeInMillis() or getTime() both return the time from the Epoch that is set to January 1, 1970 00:00:00.000 GMT (Gregorian). So if you want to print the time or use it for something other then calculate the difference in time you can use, for example:
System.out.println(cal.get(Calendar.YEAR));
However if you want to get the difference of time between this time and another you should create another calendar instance for that other time (because of the way getTimeInMillis() work). So you can just do something like:
Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
time.set(Calendar.YEAR, year);
time.set(Calendar.MONTH, month);
time.set(Calendar.DAY_OF_MONTH, day_of_month);
time.set(Calendar.HOUR_OF_DAY, hour_of_day);
time.set(Calendar.MINUTE, minute);
time.set(Calendar.SECOND, second);
long difInMillis = cal.getTimeInMillis() - time.getTimeInMillis();
Also you should always remember that the month starts from 0 and not from 1, to be sure you can use Calendar.[your_month_here] and check the values.
You can find more information here: http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html

Convert a full Java date (e.g. 8.00am 2013-06-19) to just a time (i.e. 8.00am 1970-01-01)

As part of some logic, it is necessary in my program to turn a long Java timestamp (including year, month, etc.) to a 'short' Java time. This should correspond to exactly the same hours, minutes and seconds of the original time, but within 1 day of Jan 1 1970 (i.e. a value between 0 (00:00:00) and 86400000 (23:59:59)). An example is the conversion in the question.
In order the perform this, I thought the below code would work:
public int convertToTime(long fullTimeStamp) {
Calendar c = Calendar.getInstance();
c.setTimeInMillis(date);
c.set(Calendar.DATE, 1);
c.set(Calendar.MONTH, 0);
c.set(Calendar.YEAR, 1970);
return (int) c.getTimeInMillis();
}
The issue I am having is to do with timezones. In the UK we are currently in BST. After setting all the values with the function, the time remains the same numbers (e.g. 8.00am) but changes the timezone to GMT! 8.00am GMT is of course not the same as 8.00am BST, and is instead equal to 9.00am BST.
Adding some console output to the function demonstrates this issue:
public int convertToTime(long fullTimeStamp) {
System.out.println(new Date(fullTimeStamp)); // correct
Calendar c = Calendar.getInstance();
c.setTimeInMillis(fullTimeStamp);
System.out.println(c.getTime()); // correct
c.set(Calendar.DATE, 1);
c.set(Calendar.MONTH, 0);
c.set(Calendar.YEAR, 1970);
System.out.println(c.getTime()); // incorrect!
return (int) c.getTimeInMillis();
}
Program output:
Wed Jun 19 12:15:00 BST 2013 // ok
Wed Jun 19 12:15:00 BST 2013 // this makes sense
Thu Jan 01 12:15:00 GMT 1970 // Calendar, stahp!
The desired behaviour is for the last part to read:
Thu Jan 01 11:15:00 GMT 1970
or
Thu Jan 01 12:15:00 BST 1970
Is this expected behaviour of the calendar? My understanding was that it keeps all the 'digits' the same that aren't modified, so if the value of HOUR_OF_DAY is 8, it should stay at 8, even if the timezone is modified.
I have tried setting the timezone on the calendar (before any values are set) to BST and GMT and exactly the same behaviour occurs. I also cannot manually add or remove milliseconds to delete all years after 1970 as I will have to handle leap years.
Aside from 'use Joda time (or some other time package)' does anyone have any other suggestions to perform this operation? I kind of need to get a quick fix in before experimenting with other packages if possible.
Thanks!
I think you're running foul of a little-known fact about the UK time zone: at the Unix epoch, we were actually in UTC+1. Java is getting the time of day right (within the UK time zone), but the name wrong - it shouldn't be specifying GMT, but BST. This isn't BST as in British Summer Time; it's BST as in British Standard Time. Yes, it's that mad.
From the relevant wikipedia article:
An inquiry during the winter of 1959–60, in which 180 national organisations were consulted, revealed a slight preference for a change to all-year GMT+1, but the length of summer time was extended as a trial rather than the domestic use of Greenwich Mean Time abolished.[8] A further inquiry during 1966–67 led the government of Harold Wilson to introduce the British Standard Time experiment, with Britain remaining on GMT+1 throughout the year. This took place between 27 October 1968 and 31 October 1971, when there was a reversion to the previous arrangement.
It's worth bearing in mind that your original problem statement is somewhat ambiguous: you're taking in a long, which is just the millis since the Unix epoch - but then you're trying to interpret it in terms of the hour of day, which immediately begs the question of which time zone you need to interpret it in. Have you made that decision? If so, you should document it very carefully, and make sure your code complies with it.
Ultimately, my recommendations are:
If you can possibly use Joda Time, do so. It will save you hours and hours of heartache.
If you're trying to calendar calculations like this, consider changing the time zone of the calendar to UTC before doing anything else; it will save you some heartache
Avoid using Date.toString() where possible - you could use a DateFormatter with the time zone set to UTC, and then you would see the expected results
As user2340612's answer states, to get just the "millisecond of UTC day" you can use simple arithmetic - but not quite with the values given. I would use:
long timeOfDay = millisecondsSinceUnixEpoch % TimeUnit.DAYS.toMillis(1);
... but this only works if you're interested in the UTC time of day for the given instant. (It will also give a negative result for negative input, but you may not care about that.)
If you need a timestamp between 0 and 86399999 (which is 23:59:59.999) you can get the current timestamp and calculate the remainder of the division between it and 86400000:
desired_time = cur_time % 86400000
But you'll miss the summer time, if present.

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

Categories