Joda-Time - Number of seconds between two dates - java

My english is not perfect, but I hope you can understand me.
I try to get the difference in seconds between two unix timestamps, but it's only return 0.
That's my code
unixOnline = Long.valueOf(online);
unixOffline = Long.valueOf(offline);
DateTimeZone BERLIN = DateTimeZone.forID("Europe/Berlin");
DateTime dateTimeOnline = new DateTime(unixOnline * 1000L, BERLIN);
DateTime dateTimeOffline = new DateTime(unixOffline * 1000L, BERLIN);
int seconds = Seconds.secondsBetween(new LocalDate(dateTimeOnline), new LocalDate(dateTimeOffline)).getSeconds();
System.out.println("Seconds: " + seconds);
Edit:
Online Timestamp: 1457536522
Offline Timestamp: 1457536642

LocalDate has no time component, so if the times are on the same day, they're effectively turned into the same time. Instead, just diff the DateTimes as they are;
int hours = Hours.hoursBetween(dateTimeOnline, dateTimeOffline).getHours();
(or in your case, since the difference is only 2 minutes, you'll only see the result with Minutes or Seconds)
EDIT: Since the question seems to have nothing to do with the time zone BERLIN which is in the code, this answer is a bit over complicated. Instead, use krzydyn's answer if it's just a time diff between UTC times.

Since you already have timestamps in seconds it can be simple calculated by formula:
int hours = (t2-t1)/3600;
Or if you need fractions:
float hours = (t2-t1)/3600f;
Update: (maybe I got suggested by the answer :)
So to get time diff in seconds is even simpler:
long seconds = t2-t1;

Related

Strip seconds and milliseconds from System.currentTimeMillis value

Suppose I have a System.currentTimeMillis() value as a long number.
How do I modify it to match the instant when last minute started? I.e., zero out seconds and milliseconds.
I would prefer to not use magic constants. Using java.time is fine.
I agree with the answers recommending java.time, but it can be done yet simpler as in those answers:
long lastWholeMinute = Instant.now().truncatedTo(ChronoUnit.MINUTES).toEpochMilli();
This just gave 1517940060000. Of course, if it makes sense for you to keep the Instant object, by all means do that rather than converting to a naked primitive long.
If your long value was one you had stored rather than the time now, it’s quite similar:
long someEpochMilliValue = 1_517_941_234_567L;
long lastWholeMinute = Instant.ofEpochMilli(someEpochMilliValue)
.truncatedTo(ChronoUnit.MINUTES)
.toEpochMilli();
Using java.time is probably the easiest way. You could use withNano and withSecond, like
java.time.ZonedDateTime zdt = java.time.ZonedDateTime.now().withNano(0).withSecond(0);
long millis = zdt.toInstant().toEpochMilli();
Since the value is in milliseconds, if we assume an idealized day (no leap seconds, etc.), then given l you could do it by simply removing the value of l % 60000L from it. I realize that's a magic constant, but it's truly a constant, there are always going to be 60,000 milliseconds in a minute. I'd give it symbolic name:
private static long SIXTY_SECONDS_IN_MS = 60000L;
and not worry about it. Then it's:
long l = /*...your number...*/;
l = l - (l % SIXTY_SECONDS_IN_MS);
Why this works: The Epoch value is from midnight Jan 1st 1970, and so at 0L, 60000L, 120000L, etc., the seconds and milliseconds of an idealized day based on that value are 0. So we use the remainder operator (%) to isolate the part of the value that would remain if we divided by 60000L and remove it. Thus the resulting value, again assuming idealized days, has 0 for seconds and milliseconds. It also works across timezones if we assume all timezones are going to be at whole-minute offsets to UTC. I've only ever heard of timezones that were multiples of hours or half-hours offset from UTC ("GMT plus five hours", "GMT plus 5.5 hours"), never (say) "GMT plus five hours seven minutes and 20 seconds". (And indeed, the standard notation for timezome offsets, +0600 or similar, only includes hours and minutes, not fractional minutes.)
Live Example:
import java.time.*;
public class Example
{
private static long SIXTY_SECONDS_IN_MS = 60000L;
public static void main (String[] args) throws java.lang.Exception
{
long l = System.currentTimeMillis();
l = l - (l % SIXTY_SECONDS_IN_MS);
System.out.println("l = " + l);
// Checking the result
LocalDateTime dt = Instant.ofEpochMilli(l).atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(dt);
System.out.println(dt.getSecond()); // 0
System.out.println(dt.getNano()); // 0
}
}
Still, though, if that constant violates the terms of the question such that you think I shouldn't have answered, let me know and I'll delete the answer. :-)

Found weird behavior with Joda API

I started looking at joda API for handling timezone related issues for my web application. I found very weird behavior while doing so. I hope there must be some workaround. here is my snap-code.
DateTime utcDateTime = new DateTime(System.currentTimeMillis(), DateTimeZone.UTC);
DateTime currentDateTime = DateTime.now();
int seconds = Seconds.secondsBetween(utcDateTime.toLocalDateTime(), currentDateTime.toLocalDateTime()).getSeconds();
System.out.println("hours::" + (((float)seconds)/(60*60)));
My local timezone is : kolkata, India (GMT + 5:30)
then I should get 5.5 as myn console output, but I am getting hours::5.499722
Don't know Why? Am I doing anything wrong?
(5.5 hours - 5.499722 hours) in ms
=
1000.8 ms
1 second, to the rounding/floating point precision. You call
DateTime utcDateTime = new DateTime(System.currentTimeMillis(), DateTimeZone.UTC);
DateTime currentDateTime = DateTime.now();
Seconds.secondsBetween().getSeconds() gives you an integer number of seconds. Your calls are successive meaning they can be off by even 1 millisecond, which can be rounded to 1 second when converted to int.
Given that you want hours and minutes (an Hours object can only hold an integer number of hours) you probably want:
Period period = new Period(utcDateTime.toLocalDateTime(),
currentDateTime.toLocalDateTime(),
PeriodType.time());
Or alternatively, and more cleanly IMO:
int offsetMillis = DateTimeZone.getDefault().getOffset(Instant.now());
Duration offset = Duration.millis(offsetMillis);
You should very rarely need to know the offset in this fashion though, in my experience.

Represent date from long, starting from year 0 instead of 1970 [duplicate]

This question already has an answer here:
How to calculate difference between two dates in years...etc with Joda-Time
(1 answer)
Closed 8 years ago.
I have a long-variable which represents an amount of delay in milliseconds. I want to transform this long to some kind of Date where it says how many hours, minutes, seconds, days, months, years have passed.
When using Date toString() from Java, as in new Date(5).toString, it says 5 milliseconds have passed from 1970. I need it to say 5 milliseconds have passed, and 0 minutes, hours, ..., years.
you cannot get direct values , without any reference date for your requirements, you need define first reference value like below:
String dateStart = "01/14/2012 09:29:58";
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss")
Date d1 = format.parse(dateStart);
the above is your reference date , now you need to find the current date and time using following.
long currentDateTime = System.currentTimeMillis();
Date currentDate = new Date(currentDateTime);
Date d2.format(currentDate)
and the difference of these values like long diff=d2-d1 will gives values in milliseconds.
then
long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffDays = diff / (24 * 60 * 60 * 1000);
and similarly for months and years.
you can also refer the example given on this link for more information http://javarevisited.blogspot.in/2012/12/how-to-convert-millisecond-to-date-in-java-example.html
From what I understand from your question you could achieve your goal by writing a method that will suit your needs i.e.:
static public String dateFromMili (long miliseconds) {
// constants that will hold the number of miliseconds
// in a given time unit (year, month etc.)
final int YEAR_IN_MILISECONDS = 12*30*24*60*60*1000;
final int MONTH_IN_MILISECONDS = 30*24*60*60*1000;
final int DAY_IN_MILISECONDS = 24*60*60*1000;
final int HOUR_IN_MILISECONDS = 60*60*1000;
final int MINUTE_IN_MILISECONDS = 60*1000;
final int SECONDS_IN_MILISECONDS = 1000;
// now use those constants to return an appropriate string.
return miliseconds +" miliseconds, "
+miliseconds/SECONDS_IN_MILISECONDS+" seconds, "
+miliseconds/MINUTE_IN_MILISECONDS+" minutes, "
+miliseconds/HOUR_IN_MILISECONDS+" hours, "
+miliseconds/DAY_IN_MILISECONDS+" days, "
+miliseconds/MONTH_IN_MILISECONDS+" months, "
+miliseconds/YEAR_IN_MILISECONDS+" years have passed";
}
Than you will have to pas the number of miliseconds as a parameter to your new function that will return the desired String (i.e for two seconds):
dateFromMili (2000);
You could also print your answer:
System.out.println(dateFromMili(2000));
The result would look like this:
2000 miliseconds, 2 seconds, 0 minutes, 0 hours, 0 days, 0 months, 0 years have passed
Note that this method will return Strings with integer value (you will not get for example "2.222333 years" but "2 years"). Furthermore, it could be perfected by changing the noun from plural to singular, when the context is appropriate ("months" to "month").
I hope my answer helped.
This is how I solved the problem:
I used a library called Joda-Time (http://www.joda.org/joda-time/) (credits to Keppil!)
Joda-Time has various data-structures for Date and Time. You can represent a date and time by a DateTime-object.
To represent the delay I was looking for, I had two options: a Period data-structure or a Duration data-structure. A good explanation of the difference between those two can be found here: Joda-Time: what's the difference between Period, Interval and Duration? .
I thus used a Duration-object, based on the current date of my DateTime-object. It has all the methods to convert the amount of milliseconds to years, months, weeks, days, hours, minutes and seconds.

Time computation in Millis is not producing the expected outcome. Can somebody help tell why?

I have the following code that normally would take some instances of time, convert them to milliseconds to make some fairly precise computations, and produce the equivalent day(s) between those times OR hour(s) between them as the case may be. I think the code best explains what I am trying to achieve. Following are some snippets...
private int hours = 0;
/* This is intended to get the days between 'startDate' and 'endDate'
* and ensure it is between zero & the specified 'range' of days, inclusive*/
public int getPeriodBtw(Date startDate, Date endDate, int range)
{
int daysBtw = 0;
Calendar constantDate = Calendar.getInstance();
constantDate.setTime(startDate);
Calendar currentDate = Calendar.getInstance();
currentDate.setTime(endDate);
long rangePeriod = Period.ConvertDaysToMillis(range);
long duration = (constantDate.getTimeInMillis() + rangePeriod) - currentDate.getTimeInMillis();
daysBtw = (int)Period.ConvertMillisToDays(duration);
if(duration >= 0 && duration <= rangePeriod)
{
if(daysBtw == 0){
hours = (int)Period.ConvertMillisToHours(duration);
}
}
return daysBtw;
}
Now, the logic above seems all knit tight and good to me, but surprisingly, I get odd results as currentDate changes. I mean, normally I would expect something like this... See the following Illustration;
If constantDate = 10:00am
If range = 1 day starting from constantDate
and lets say currentDate = 2:00pm on the same day (i.e within range),
then daysBtw should return = 0
hours between constantDate and currentDate is 4hrs
Now this means currentDate is 4hrs Less range,
Thus duration should be 1day(24hrs) - 4hrs = 20hrs
Of course I think handling this in Millisecond offset from epoch wld be something like so;
10:00am(millis) + 1day(millis) - 2:00pm(millis) = 20hrs
long duration = (constantDate.getTimeInMillis() + rangePeriod) - currentDate.getTimeInMillis();
hours = (int)Period.ConvertMillisToHours(duration);
so hours should return = 20
Now, if currentDate changes to 3:00pm, following the same logic previously described, shouldn't hours = 19???... Problem is, my program gets hours = 21 instead.
I've been really confused as to what I might be doing wrong. Is the problem with my Logic???... Or is it somewhere in my Code???... I feel terribly bad admitting that I've spent a few hours on and off this thing that I know is rather simple, But time is not my friend as usual, and I have to move on to things less trivial. Any form of help would be highly appreciated. Thanks Y'all!
Okay... I did find a solution to this issue earlier on... Turned out it was due to;
1. some bad logic on my side, and also
2. some loss of precision when using java.util.concurrent.TimeUnit to convet Milliseconds to Days
TimeUnit.DAYS.convert(args, TimeUnit.MILLISECONDS);
It still beats me why they had to make the convert method recieve its milliseconds argument as long and return days as long too, without creating an option to set the preferred RoundingMode.... Anyways, its been added to my short list of ( STAY-AWAY-FROM-IT ) API's. Lolz!

How can I learn how many days passed from a specific date?

How can I learn how many days passed from a spesific date? Which package i need to use and how?
Just for the protocol - i love java.util.concurrent.TimeUnit for that things.
Date d1 = ...
Date d2 = ...
long dif = d1.getTime() - d2.getTime();
long days = TimeUnit.MILLISECONDS.toDays(dif);
So basically exactly what the answer from morja is, but using TimeUnit for calculating time things around. Having values like 24, 60 etc. directly in your code violates Java Code Conventions (which only allow -1, 0 and 1 directly in code) and is harder to read.
EDIT My previous answer was only valid within a year.
You can use the milliseconds difference like this:
Date date1 = // some date
Date date2 = // some other date
long difference = date2.getTime() - date1.getTime();
long differenceDays = difference / (1000 * 60 * 60 * 24);
Basically the same as timbooo answered, just a shorter way.
Check out this example by kodejava.org
Jodatime makes such calculations a lot simpler:
Date now = // some Date
Date then = // some Date
int days = Days.daysBetween(new DateTime(now), new DateTime(then)).getDays();
In fact, you should create instances of Calendar from both of the dates, getTimeInMillis() from both of them (that is, time in milliseconds since 1970), substract one from the other, divide by 1000/seconds-a-minute/minute-an-hour/hour-a-day. There is your answer ;)

Categories

Resources