milliseconds to days - java

i did some research, but still can't find how to get the days... Here is what I got:
int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours = (int) ((milliseconds / (1000*60*60)) % 24);
int days = ????? ;
Please help, I suck at math, thank's.

For simple cases like this, TimeUnit should be used. TimeUnit usage is a bit more explicit about what is being represented and is also much easier to read and write when compared to doing all of the arithmetic calculations explicitly. For example, to calculate the number days from milliseconds, the following statement would work:
long days = TimeUnit.MILLISECONDS.toDays(milliseconds);
For cases more advanced, where more finely grained durations need to be represented in the context of working with time, an all encompassing and modern date/time API should be used. For JDK8+, java.time is now included (here are the tutorials and javadocs). For earlier versions of Java joda-time is a solid alternative.

If you don't have another time interval bigger than days:
int days = (int) (milliseconds / (1000*60*60*24));
If you have weeks too:
int days = (int) ((milliseconds / (1000*60*60*24)) % 7);
int weeks = (int) (milliseconds / (1000*60*60*24*7));
It's probably best to avoid using months and years if possible, as they don't have a well-defined fixed length. Strictly speaking neither do days: daylight saving means that days can have a length that is not 24 hours.

Go for TImeUnit in java
In order to import use, java.util.concurrent.TimeUnit
long millisec=System.currentTimeMillis();
long seconds=TimeUnit.MILLISECONDS.toSeconds(millisec);
long minutes=TimeUnit.MILLISECONDS.toMinutes(millisec);
long hours=TimeUnit.MILLISECONDS.toMinutes(millisec);
long days=TimeUnit.MILLISECONDS.toDays(millisec);

java.time
You can use java.time.Duration which is modelled on ISO-8601 standards and was introduced with Java-8 as part of JSR-310 implementation. With Java-9 some more convenient methods were introduced.
Demo:
import java.time.Duration;
public class Main {
public static void main(String[] args) {
// Duration between the two instants
Duration duration = Duration.ofMillis(1234567890L);
// Print Duration#toString
System.out.println(duration);
// Custom format
// ####################################Java-8####################################
String formattedElapsedTime = String.format(
"%d Day %02d Hour %02d Minute %02d Second %d Millisecond (%d Nanosecond)", duration.toDays(),
duration.toHours() % 24, duration.toMinutes() % 60, duration.toSeconds() % 60,
duration.toMillis() % 1000, duration.toNanos() % 1000000000L);
System.out.println(formattedElapsedTime);
// ##############################################################################
// ####################################Java-9####################################
formattedElapsedTime = String.format("%d Day %02d Hour %02d Minute %02d Second %d Millisecond (%d Nanosecond)",
duration.toDaysPart(), duration.toHoursPart(), duration.toMinutesPart(), duration.toSecondsPart(),
duration.toMillisPart(), duration.toNanosPart());
System.out.println(formattedElapsedTime);
// ##############################################################################
}
}
A sample run:
PT342H56M7.89S
14 Day 06 Hour 56 Minute 07 Second 890 Millisecond (890000000 Nanosecond)
14 Day 06 Hour 56 Minute 07 Second 890 Millisecond (890000000 Nanosecond)
Learn more about the modern date-time API from Trail: Date Time.

int days = (int) (milliseconds / 86 400 000 )

public static final long SECOND_IN_MILLIS = 1000;
public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
You could cast int but I would recommend using long.

You can’t. Sorry. Or more precisely: you can if you know a time zone and a start time (or end time). A day may have a length of 23, 24 or 25 hours or some other length. So there isn’t any sure-fire formula for converting from milliseconds to days. So while you can safely rely on 1000 milliseconds in a second, 60 seconds in a minute (reservation below) and 60 minutes in an hour, the conversion to days needs more context in order to be sure and accurate.
Reservation: In real life a minute is occasionally 61 seconds because of a leap second. Not in Java. Java always counts a minute as 60 seconds because common computer clocks don’t know leap seconds. Common operating systems and Java itself do know not only summer time (DST) but also many other timeline anomalies that cause a day to be shorter or longer than 24 hours.
To demonstrate. I am writing this on March 29, 2021, the day after my time zone, Europe/Copenhagen, and the rest of the EU switched to summer time.
ZoneId myTimeZone = ZoneId.of("Europe/Copenhagen");
ZonedDateTime now = ZonedDateTime.now(myTimeZone);
ZonedDateTime twoDaysAgo = now.minusDays(2);
ZonedDateTime inTwoDays = now.plusDays(2);
System.out.println(ChronoUnit.MILLIS.between(twoDaysAgo, now));
System.out.println(ChronoUnit.MILLIS.between(now, inTwoDays));
Output:
169200000
172800000
So how many milliseconds are in two days depends on which two days you mean. And in which time zone.
So what to do?
If for your purpose you can safely define a day as 24 hours always, for example because your days are counted in UTC or your users are fine with the inaccuracy, use either Duration or TimeUnit. Since Java 9 the Duration class will additionally tell you how many hours, minutes and seconds there are in addition to the whole days. See the answer by Arvind Kumar Avinash. For the TimeUnit enum see the answers by whaley and Dev Parzival. In any case the good news is that it doesn’t matter if you suck at math because the math is taken care of for you.
If you know a time zone and a starting point, use ZonedDateTime and ChronoUnit.DAYS. In this case too the math is taken care of for you.
ZonedDateTime start = LocalDate.of(2021, Month.MARCH, 28).atStartOfDay(myTimeZone);
long millisToConvert = 170_000_000;
ZonedDateTime end = start.plus(millisToConvert, ChronoUnit.MILLIS);
long days = ChronoUnit.DAYS.between(start, end);
System.out.format("%d days%n", days);
2 days
If you additionally want the hours, minutes and seconds:
Duration remainingTime = Duration.between(start.plusDays(days), end);
System.out.format(" - and an additional %s hours %d minutes %d seconds%n",
remainingTime.toHours(),
remainingTime.toMinutesPart(),
remainingTime.toSecondsPart());
- and an additional 0 hours 13 minutes 20 seconds
If instead you had got an endpoint, subtract your milliseconds from the endpoint using the minus method (instead of the plus method used in the above code) to get the start point.
Under no circumstances do the math yourself as in the question and in the currently accepted answer. It’s error-prone and results in code that is hard to read. And if your reader sucks at math, he or she can spend much precious developer time trying to verify that you have done it correctly. Leave the math to proven library methods, and it will be much easier for your reader to trust that your code is correct.

In case you solve a more complex task of logging execution statistics in your code:
public void logExecutionMillis(LocalDateTime start, String callerMethodName) {
LocalDateTime end = getNow();
long difference = Duration.between(start, end).toMillis();
Logger logger = LoggerFactory.getLogger(ProfilerInterceptor.class);
long millisInDay = 1000 * 60 * 60 * 24;
long millisInHour = 1000 * 60 * 60;
long millisInMinute = 1000 * 60;
long millisInSecond = 1000;
long days = difference / millisInDay;
long daysDivisionResidueMillis = difference - days * millisInDay;
long hours = daysDivisionResidueMillis / millisInHour;
long hoursDivisionResidueMillis = daysDivisionResidueMillis - hours * millisInHour;
long minutes = hoursDivisionResidueMillis / millisInMinute;
long minutesDivisionResidueMillis = hoursDivisionResidueMillis - minutes * millisInMinute;
long seconds = minutesDivisionResidueMillis / millisInSecond;
long secondsDivisionResidueMillis = minutesDivisionResidueMillis - seconds * millisInSecond;
logger.info(
"\n************************************************************************\n"
+ callerMethodName
+ "() - "
+ difference
+ " millis ("
+ days
+ " d. "
+ hours
+ " h. "
+ minutes
+ " min. "
+ seconds
+ " sec."
+ secondsDivisionResidueMillis
+ " millis).");
}
P.S. Logger can be replaced with simple System.out.println() if you like.

Related

How to transfer Date.getTime() to hours and calculating difference

I have a program that is intaking an "AM" "PM" time and calculating out the hours in the day equivalent (in 24 hour format). For some reason it parses and calculates the time I input to the incorrect 24 hour equivalent (ie 5:00 pm comes to equal 22)
System.out.print("Enter the end time (HH:MM am): ");
endTime = input.nextLine();
Date ETime = time_to_date.parse(endTime);
Class method
public int get_Family_A_Calulation(Date STime, Date ETime) {
Date startTimeCalc = STime, endTimeCalc = ETime;
int pay = 0, hoursWorked, StartHour, EndHour;
StartHour = ((((int) startTimeCalc.getTime()) / 1000) / 60) / 60;
EndHour = ((((int) endTimeCalc.getTime()) / 1000) / 60) / 60;
pay = hoursWorked * 15;
return pay;
}
I am not sure where my error is can anyone give me advice on how to correct this error?
Use the latest classes available fron java8
LocalDateTime now = LocalDateTime.now();
System.out.println(now.getHour());
The actual data behind Date is milliseconds since the epoch. Any hour or time representation is based on the calendar date portion and takes into account timezone and daylight savings.
Regardless of what you do, there will be calculation issues across days, etc.
As suggested by Scary Wombat, use the new classes in java.time package. For your specific case, you need a LocalTime as the code is trying to represent a time element (hours, minutes, seconds, etc) without consideration for Date, TimeZone, etc.
https://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html

How to calculate 2 Unix timeSpan difference. e.g. int endTime=1213036458; int startTime= 1211018446;

How do we calculate the Unix timeSpan in Java?
int endTime=1213036458;
int startTime= 1211018446;
The result should be in hours.
Unix time is usually (from the Wikipedia link) defined as the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970. That particular epoch is shared by Java, but Java uses milliseconds instead of seconds.
If you're using Java 8+ you could use a Duration like
int endTime = 1213036458;
int startTime = 1211018446;
Duration d = Duration.ofSeconds(endTime - startTime);
System.out.println(d);
Which gives me (560 hours, 33 minutes and 32 seconds)
PT560H33M32S
If you're using an older version of Java you could always implement it with something like
int seconds = endTime - startTime;
int hours = seconds / 3600;
seconds -= hours * 3600;
int minutes = seconds / 60;
seconds -= minutes * 60;
System.out.printf("%d hours, %d minutes and %d seconds%n", hours,
minutes, seconds);
And I get the expected
560 hours, 33 minutes and 32 seconds

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.

What happened between March 28th and March 29th, 1976 with the java.util.GregorianCalendar?

Trying to use the GregorianCalendar, I got stuck on a singularity while computing the number of days since a particular date.
In the scala interpreter, I entered :
scala>import java.util.GregorianCalendar
scala>import java.util.Calendar
scala>val dateToday = new GregorianCalendar(2012,Calendar.MAY,22).getTimeInMillis()
dateToday: Long = 1337637600000
scala>val days1 = (dateToday - (new GregorianCalendar(1976,Calendar.MARCH,28).getTimeInMillis())) / (1000*3600*24)
days1: Long = 13203
scala>val days2 = (dateToday - (new GregorianCalendar(1976,Calendar.MARCH,29).getTimeInMillis())) / (1000*3600*24)
days2: Long = 13203
I don't know if the fact that 1976 is a leap year matters, but days1 and days2 should have been separated by 1. This is the only moment in history since 1970 that this singularity happens.
Wanting to know what is going on, I compute the difference between the two dates previously mentionned, and it gives me only exactly 23 hours of difference ! What happened on that date ? Wikipedia apparently says nothing about it.
And even more important, how to compute the real number of days since a particular date ?
The Problem
Daylight savings days are only 23 hours long.
And according to this March 28th, 1976 was a daylight savings day in at least Paris. The hour between 1am and 2am on that day simply did not exist.
Though it must be a Locale issue since on my computer I get it right:
scala> val days1 = (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 28).getTimeInMillis())) / (1000 * 3600 * 24)
days1: Long = 13203
scala> val days2 = (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 29).getTimeInMillis())) / (1000 * 3600 * 24)
days2: Long = 13202
I'm not in Paris or anywhere else that had a time change on that day; the time changed on April 25, 1976 where I am. So I get the "skipped day" behavior on that date:
scala> val days3 = (dateToday - (new GregorianCalendar(1976, Calendar.APRIL, 25).getTimeInMillis())) / (1000 * 3600 * 24)
days3: Long = 13175
scala> val days4 = (dateToday - (new GregorianCalendar(1976, Calendar.APRIL, 26).getTimeInMillis())) / (1000 * 3600 * 24)
days4: Long = 13175
Erwin points on in the comments that the likely reason your only noticing the incorrect date difference here is that all of the other daylight savings days are offset by the 25-hour days that also happen in those years, when the daylight savings day is corrected.
The Solution
Use a better library for date processing. The joda-time library does it correctly (as well as being a better date/time framework overall):
import org.joda.time.Days
import org.joda.time.DateTimeConstants
import org.joda.time.DateMidnight
val d1 = new DateMidnight(1976, DateTimeConstants.APRIL, 25)
val d2 = new DateMidnight(1976, DateTimeConstants.APRIL, 26)
val x = Days.daysBetween(d1, d2).getDays()
println(x) // 1
If the option of a float division is not available, the best answer I can think of is to add one hour (1000*3600) while computing a difference between two days:
scala> (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 28).getTimeInMillis()) + 1000*3600) / (1000 * 3600 * 24)
days1: Long = 13204
scala> (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 29).getTimeInMillis()) + 1000*3600) / (1000 * 3600 * 24)
days1: Long = 13203
It should work for every date, as you do not suffer from leap hours anymore.
dhg pointed out what I think: This day is a "daylight saving time" day.
As this day is only 23h long, euclidian division by a day equals 0.
In fact, using GregorianCalendar objects is only using a date as milliseconds, so dividing by one day as an integer does only truncate a result.
Instead of an euclidian (integer) division, try to do a float division, then round the result.

Formatting a *relative* amount of time (ms) in Java?

I want to log certain events by their relative timing. I don't care at what hour of the day something happened, I just want to know that an event happened 2 minutes, 13 seconds and 243 milliseconds ago. Let's say I have:
long event_ms = [some time in ms since the Epoch];
long now_ms = [current time in ms since the Epoch];
long diff_ms = now_ms - event_ms;
diff_ms contains the number of milliseconds AGO that the event occurred. I just want to format this time (using the format HH:mm:ss.SSS). What's the easiest way to do this? Thanks!
The class TimeUnit contains methods to convert millis in to hours, minutes and seconds:
String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes(millis),
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
P.S Note that TimeUnit is available only in 1.5+
A simpler approach
String.format("%d min, %d sec, %d ms",
millis/60/1000, millis/1000%60, millis%1000);
You don't need TimeUnit to do simple integer operations such as division and module, nor you need to use TimeZone(s), since you are dealing with a delta, which is time-zone independent. Here's the solution I would have used:
long millis = 123456L;
String delta = String.format(
"%02d:%02d:%02d.%03d",
(millis / (1000L * 60L * 60L)),
(millis / (1000L * 60L)) % 60,
(millis / 1000L) % 60,
millis % 1000L
);
The following code works fine for me:
int diff_ms = 61200;
SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss.SSS");
fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
String str = fmt.format(new Date(diff_ms));
System.out.println(str);
It prints 00:01:01.200
Pay attention on setting the timezone. Otherwise the result depends on your default timezone and will be wrong everywhere except GMT.

Categories

Resources