Get time difference java.sql.Time - java

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.

Related

Simple date format giving wrong time

I have a time in milliseconds: 1618274313.
When I convert it to time using this website: https://www.epochconverter.com/, I am getting 6:08:33 AM.
But when I use SimpleDateFormat, I am getting something different:
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
System.out.println(sdf.format(new Date(1618274313)));
I am getting output as 23:01:14.
What is the issue in my code?
In your example, you are using time 1618274313 and you are assuming that it is in milliseconds. However, when I entered the same time on https://www.epochconverter.com/, I got below results:
Please notice the site mentions: Assuming that this timestamp is in seconds.
Now if we use that number multiplied by 1000 (1618274313000) as the input so that the site considers it in milliseconds, we get below results:
Please notice the site now mentions: Assuming that this timestamp is in milliseconds.
Now, when you will use 1618274313000 (correct time in milliseconds) in Java with SimpleDateFormat, you should get your expected result (instead of 23:01:14):
SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
System.out.println(sdf.format(new Date(1618274313000)));
use Instant.ofEpochSecond
long test_timestamp = 1618274313L;
LocalDateTime triggerTime =
LocalDateTime.ofInstant(Instant.ofEpochSecond(test_timestamp),
TimeZone.getDefault().toZoneId());
System.out.println(triggerTime);
it prints output as 2021-04-13T06:08:33
Assuming it is in milliseconds as you say, all you know for certain is that you have a specific duration.
Duration d = Duration.ofMillis(1618274313);
System.out.println(d);
Prints
PT449H31M14.313S
Which says it is 449 hours, 31 minutes and 14.313 seconds of duration. Without knowing the epoch of this duration and any applicable zone offsets, it is not really possible to ascertain the specific date/time it represents. I could make lots of assumptions and provide results based on that, but more information from you would be helpful.
java.time
As Viral Lalakia already spotted, the epoch converter that you linked to, explicitly said that it assumed that the number was seconds (not milliseconds) since the epoch. The following makes the same assumption in Java. I recommend that you use java.time, the modern Java date and time API.
ZoneId zone = ZoneId.of("Asia/Kolkata");
long unixTimestamp = 1_618_274_313;
Instant when = Instant.ofEpochSecond(unixTimestamp);
ZonedDateTime dateTime = when.atZone(zone);
System.out.println(dateTime);
System.out.println(dateTime.format(DateTimeFormatter.ISO_LOCAL_TIME));
Output is:
2021-04-13T06:08:33+05:30[Asia/Kolkata]
06:08:33
This agrees with the 6:08:33 AM that you got from the converter. And the date is today’s date. A coincidence?
If the number is indeed milliseconds (which I honestly doubt), just use Instant.ofEpochMill() instead of Instant.ofEpochSecond().
Instant when = Instant.ofEpochMilli(unixTimestamp);
1970-01-19T23:01:14.313+05:30[Asia/Kolkata]
23:01:14.313
This in turn agrees with the result you got in Java (except that the milliseconds are also printed).

Java millis time with hourly resolution

How do I get java time millis in UTC ignoring the minutes and seconds.
For instance :
If it is October 10 2019, 1:10:59 AM , it should get the Time or millis for
October 10 2019, 1 AM.
Summary:
Instant
.now()
.truncatedTo(
ChronoUnit.HOURS
)
.toEpochMilli()
1570600800000
java.time, the modern Java date and time API has got exactly the method you need: many of the classes have a truncatedTo method for needs like yours.
Instant now = Instant.now();
System.out.println("Rough milliseconds: " + now.toEpochMilli());
Instant currentWholeHour = now.truncatedTo(ChronoUnit.HOURS);
System.out.println("Milliseconds ignoring minutes and seconds: "
+ currentWholeHour.toEpochMilli());
When running this snippet just now the output was:
Rough milliseconds: 1570604053787
Milliseconds ignoring minutes and seconds: 1570600800000
I know very well that the first line is what you asked not to have. I only included it for you to see the difference.
The truncation happens in UTC. If you are in a time zone whose offset is not a whole number of hours from UTC, the results may not be as you had expected. Examples of such time zones include Asia/Kathmandu, America/St_Johns some of the year also Australia/Lord_Howe.
Link: Oracle tutorial: Date Time
You can use LocalDate#atTime:
LocalDate.now().atTime(LocalDateTime.now().getHour(), 0, 0);
This will give you current date with hour and minutes and seconds set to 0.
And to get milliseconds in UTC:
LocalDate.now().atTime(LocalDateTime.now().getHour(), 0, 0).toInstant(ZoneOffset.UTC).toEpochMilli();
Jon Skeet notices, that calling now might give unexpected results in corner cases. To be sure, we can call it once and then convert it to LocalDate with mentioned solution:
var currentTime = LocalDateTime.now();
var currentDate = currentTime.toLocalDate();
Or the other way around - get LocalDate first and use LocalDate#atStartOfDay.
Given that you're interested in UTC milliseconds, and there are a whole number of milliseconds per hour, you can do this with simple arithmetic. For most calendrical computations I really wouldn't recommend that, but in this case I think it's the simplest approach. Something like this:
private static final long MILLISECONDS_PER_HOUR = TimeUnit.HOURS.toMillis(1);
// Injecting a clock makes the method testable. You can use Clock.systemUTC()
// for the system clock.
public static long truncateMillisToHour(Clock clock) {
long millisSinceEpoch = clock.millis();
// Truncate to the nearest hour
long hoursSinceEpoch = millisSinceEpoch / MILLISECONDS_PER_HOUR;
// Then multiply up again
return hoursSinceEpoch * MILLISECONDS_PER_HOUR;
}
Note that if the clock is for before the epoch, this will round up to the nearest hour, but if you're taking the genuine "current time" then that's unlikely to be a problem.
(I wrote this answer before seeing Ole V.V.'s answer with truncatedTo, which is a very nice approach.)

SimpleDateFormat tacks on hours for no reason?

What is the proper way to turn an integer of seconds into a formatted string of hh:mm:ss in Java?
For instance:
int Seconds = 650
String Time = 00:10:50
Right now I'm using this:
String Time = new SimpleDateFormat("hh:mm:ss").format(new Date((Seconds*1000)));
But this seems to tack on hours for no reason, and I'm guessing it's because I'm misusing Date or SimpleDateFormat, but I'm too inexperienced to know what's wrong. Or is there just a built in system for this that I don't know about.
EDIT: I should point out that I know I could use simple division to peel out the hours, then the remaining minutes, then the remaining seconds, and patch all three of those pieces into a string, but I was wondering if Java has a baked-in way to do this.
You can use TimeUnit class defined in java.util.concurrent package.
for eg you want to calculate hours:
long hours=TimeUnit.SECONDS.toHours(seconds);
similar methods are available for calulating days, hours, minutes.
but mind you this will give you direct conversion to hours, so you will end up having more than 24 hours. For a proper implementation you need to first calculate the days, the do the necessary maths and the give the remaining value for calculating hours. Lastly write a string as per your required format.
There is actually a (good) reason "to tack on hours".
Date(long date) constructor's JavaDoc:
Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
So, if your JVM is not running in the GMT timezone you're off accordingly.
It's by design and logical, too:
new Date() is expected to be your current local time
new Date(0) is expected to be January 1, 1970, 00:00:00 GMT + local offset = local time
new Date(650*1000) is expected to be January 1, 1970, 00:10:50 GMT + local offset = local time
Try it the following way,
int seconds = 650;
long millis = seconds * 1000;
String format = String.format("%d:%d:%d",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis),
TimeUnit.MILLISECONDS.toSeconds(millis)
- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
System.out.println(format);
your code is correct .but problem is this gives you the time relative to start position .think if you run following code
String Time = new SimpleDateFormat("EEEE,MMMM d,yyyy hh:mm,a").format(new Date((0)));
System.out.println(Time);
output>>Wednesday,December 31,1969 04:00,PM //this 04 will be reason to your undesired output later
i think that is the minimum time for positive seconds .think when you give milliseconds 0 java gives you day as Wednesday and 4 hours ,so starting hours of java time is not 0.
so when you run
following code
String Time = new SimpleDateFormat("hh:mm:ss").format(new Date((Seconds*1000)));
output>> 04:10:50 //you expect 00:10:50
because `starting time+seconds`
04:00:00 + 00:10:50
but starting minutes and seconds are 0 so you only have problem about hours
if you can subtract starting hours then you will get desired output.
joda time library has interval so you can use it .take a look at this question

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

How to get the time difference between 2 dates in millisec using JodaTime

I'm going to design an application, in which I need to get the exact time difference between two dates. Ex:
Date1:31/05/2011 12:54:00
Date2:31/05/2011 13:54:00
I tried using getTime() but I didn't get exact result.
The expected output for the above inputs is 3600000 (60 * 60 * 1000) millisec but I'm getting 46800000 (13 * 60 * 60 * 1000).
When I went through different java forums people are suggesting to use JodaTime.
Still I'm unable to get the exact result.
The timezone on I'm working is London(GMT).
Init two dateTime and use Period :
DateTime dt1 = new DateTime(2013,9,11,9,58,56);
DateTime dt2 = new DateTime(2013,9,11,9,58,59);
Period p = new Period(dt1, dt2, PeriodType.millis());
To get difference in milliseconds :
System.out.println(p.getValue(0));
public static long getDiff(Calender cal1, Calender cal2)
{
return Math.abs(cal1.getTimeInMillis() - cal2.getTimeInMillis());
}
Check out secondsBetween( )
Creates a Seconds representing the number of whole seconds between the
two specified partial datetimes.
The two partials must contain the same fields, for example you can
specify two LocalTime objects.
Parameters:
start - the start partial date, must not be null
end - the end partial date, must not be null
Returns:
the period in seconds
JodaTime is using machine time inside. So to find miliseconds, you can use a constant storing LocalDateTime referring to Jan 1, 1970(Because of UNIX Time).
Unix time, or POSIX time, is a system for describing points in time,
defined as the number of seconds elapsed since midnight proleptic
Coordinated Universal Time (UTC) of January 1, 1970, not counting leap
seconds. Then calculate the difference between your DateTime.
I tried like this;
public static void main(String[] args) {
final LocalDateTime JAN_1_1970 = new LocalDateTime(1970, 1, 1, 0, 0);
DateTime local = new DateTime().withZone(DateTimeZone.forID("Europe/Amsterdam"));
DateTime utc = new DateTime(DateTimeZone.UTC);
System.out.println("Europe/Amsterdam milis :" + new Duration(JAN_1_1970.toDateTime(DateTimeZone.forID("Europe/Amsterdam")), local).getMillis());
System.out.println("UTC milis :" + new Duration(JAN_1_1970.toDateTime(DateTimeZone.UTC), utc).getMillis());
}
And the result is;
Europe/Amsterdam milis :1429695646528
UTC milis :1429692046534
And #leonbloy write here a good comment.
Your local and utc represent the same instants of time, (only with
different timezones attached). Hence, getMillis() (which gives the
"physical" time interval elapsed from the "instant" corresponding to
the unix epoch), must return the same value.
Joda is a perfect library but if you need the difference between 2 dates in milliseconds you just should calculate difference between getTime(). If you get wrong results you have some problems with timezones or so. Typically it works.

Categories