difference in seconds between two dates using joda time? - java

Suppose there are two dates A(start time) & B(end time). A & B could be the time on the same day or even different day. My task is to show difference in seconds. Date format which i am using is
Date Format :: "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
For e.g.
start date :: "2011-11-16T14:09:23.000+00:00"
end date :: "2011-11-17T05:09:23.000+00:00"
Help is appreciated.

Use the Seconds class:
DateTime now = DateTime.now();
DateTime dateTime = now.plusMinutes(10);
Seconds seconds = Seconds.secondsBetween(now, dateTime);
System.out.println(seconds.getSeconds());
This piece of code prints out 600. I think this is what you need.
As further advice, explore the documentation of joda-time. It's pretty good, and most things are very easy to discover.
In case you need some help with the parsing of dates (It's in the docs, really), check out the related questions, like this:
Parsing date with Joda with time zone

The answer of #pcalcao will be best in most cases. Be aware that seconds will be rounded to an integer.
If you are interested in sub-seconds accuracy just substract the milliseconds:
double seconds = (now.getMillis() - dateTime.getMillis()) / 1000d;

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.)

No. of days between two timestamps

I have two timestamp values. like
Timestamp date1;
Timestamp date2;
Now I want to find no. of days between these two timeStamps like in java
int no_of_days = difference(date2 - date1)
the above codes are just for clarification of the question. just ignore the coding mistakes.
You can use Duration for this (it works for java 8) :
Duration between = Duration.between(date1.toInstant(), date2.toInstant());
int no_of_days = between.get(ChronoUnit.DAYS);
If you are using Java8, it will be much easier. Here's a one way of doing it.
Duration.between(date1.toLocalDateTime(), date2.toLocalDateTime()).toDays();
Other answers given here so far only handle a day unit as fixed amount of 24 hours by using the class java.time.Duration. If you consider your timestamps in the context of daylight saving switching time zones then this is probably not what you want.
During the change from winter to summer time, a calendar day can last only 23 hours (or even 23:30 in some rare cases). And in autumn when switching back to winter time, the calendar days can be more than 24 hours long. So you also need a time zone to handle this situation in order to calculate durations in the correct way.
Suggested solution if your timestamps have been stored in the database coming from instants:
ZonedDateTime zdt1 = date1.toInstant().atZone(ZoneId.systemDefault());
ZonedDateTime zdt2 = date2.toInstant().atZone(ZoneId.systemDefault());
long days = java.time.temporal.ChronoUnit.DAYS.between(zdt1, zdt2);
Of course, you are free to specify any other zone than the system time zone. The result can vary depending on the chosen zone.
Suggested solution if your timestamps have been stored coming from LocalDateTime without any zone context:
LocalDateTime ldt1 = date1.toLocalDateTime();
LocalDateTime ldt2 = date2.toLocalDateTime();
long days = java.time.temporal.ChronoUnit.DAYS.between(ldt1, ldt2);
Here I still prefer the enum ChronoUnit.DAYS because the type java.time.Duration internally stores seconds and nanoseconds only and is hence rather designed for machine-like timestamps. And another remark: The second solution implicitly uses your system time zone for the conversion from java.sql.Timestamp to LocalDateTime. This is only correct if you also have stored your timestamps that way.
By the way, with a JDBC-4.2-compliant driver, you could also retrieve your java.time-type directly, see also a related post here on SO.

Formatting time intervals with localization in Java

We have intervals (elapsed time between two oracle timestamps) stored in our database as seconds and we format them at front end with Java.
What we would to achieve on the reports is a format of the form "HH:MM" or "HH:MM:SS", with the time separator ":" localized as it happens with dates and time information, i.e '.' for Italian and ':' for English.
Unfortunately the date-related formatting classes, like SimpleDateFormat, do not work** because we can expect durations above the 24 hours.
We don't want to employ 3rdy party library as well.
Do you know how we can solve this problem?
TIA
If you want hours of more than 24 you can print this separately.
int hour = time / 3600000;
String duration = time + new SimpleDateFormat(":mm:ss").format(new Date(time));
To support other locales you could do this more complicated example.
int hour = time / 3600000;
String duration = hour
+ DateFormat.getDateInstance(DateFormat.MEDIUM, locale)
.format(new Date(time % 3600000).substring(1);
What this will do is use the locale specific format for the last digit of the hour + mins + secs and prepend the additional digits of the hours. Note: this will not work for negative times.
You can construct a date object, say "2000-01-01", then add your seconds to it. Then you can use this to extract the localized version of the time:
DateFormat format = DateFormat.getTimeInstance(DateFormat.MEDIUM, locale);
String formatted_time_part = format.format(some_date_object);
Finally you still need to add elapsed days! I'm affraid that localization of long intervals (days, months, years, centuries) has no corresponding API in Java but I might be wrong. So you will have to figure out that for yourself.

Timer - How do I calculate the difference between two dates using Joda Time?

I want to get the difference between two times P (start time) and Q (end time) using Joda Time. P and Q could be times on different days or even on the same day. I want to get the difference in format HH-MM-SS, where H=hours, M=minutes, S=seconds.
I want to use this functionality in a timer. I assume that no one will use my timer to measure more than 24 hours.
Please guide me to do this.
Take a look at the Joda time FAQ
http://joda-time.sourceforge.net/faq.html#datediff
And you can use a PeriodFormatter to get the format of your choice. Try the following sample code.
DateTime dt = new DateTime();
DateTime twoHoursLater = dt.plusHours(2).plusMinutes(10).plusSeconds(5);
Period period = new Period(dt, twoHoursLater);
PeriodFormatter HHMMSSFormater = new PeriodFormatterBuilder()
.printZeroAlways()
.minimumPrintedDigits(2)
.appendHours().appendSeparator("-")
.appendMinutes().appendSeparator("-")
.appendSeconds()
.toFormatter(); // produce thread-safe formatter
System.out.println(HHMMSSFormater.print(period));
I admire the Joda date/time API. It offers some cool functionality and if I needed an immutable calendar or some of the esoteric calendar options it offers, I'd be all over it.
It is still an external API though.
So ... why use it when you don't have to. In the Joda API, the "Instant" is the exact same thing as a Java API "Date" (or pretty close to it). These are both thin wrappers around a long that represents an instant in POSIX EPOCH UTC time (which is the number of milliseconds that have elapsed since 00:00am Jan 1, 1970 UTC.
If you have either two Instants or two Dates, computing the days between them is trivial, and the Joda library is absolutely not needed for this purpose alone:
public double computeDaysBetweenDates(Date earlier, Date later) {
long diff;
diff = later.getTime() - earlier.getTime();
return ((double) diff) / (86400.0 * 1000.0);
}
This assumes that the number of seconds in a day is 86400 ... and this is mostly true.
Once you have a difference as a double, it is trivial to convert the fractional portion of the answer (which is the fraction of one day) into HH:MM:SS.

Categories