I have a Java function that convert seconds to an specific format (hh:mm:ss):
public static String formatChronometer(long seconds) {
return String.format("%02d:%02d:%02d", TimeUnit.SECONDS.toHours(seconds),
TimeUnit.SECONDS.toMinutes(seconds) % TimeUnit.HOURS.toMinutes(1),
TimeUnit.SECONDS.toSeconds(seconds) % TimeUnit.MINUTES.toSeconds(1));
}
My client want to show this chronometer without the "hour" labels. Example:
if 100 hours => 6000:00
if 0 hours and 50 minutes => 50:00
if 1 hour and 12 minutes and 30 seconds => 72:30
if 10 hours and 5 minutes => 600:05
if 0 hours, 0 minutes and 0 seconds => 00:00
How should I change my method?
For flexible minutes number you have to use %d instead of %02d which specify how many digit you want, your solution should look like this :
return String.format("%d:%02d",
TimeUnit.SECONDS.toMinutes(seconds),
TimeUnit.SECONDS.toSeconds(seconds) % TimeUnit.MINUTES.toSeconds(1)
);
Example
long[] times = {360000, 3000, 4350, 36300, 0};
for (long time : times) {
String result = String.format("%d:%02d",
TimeUnit.SECONDS.toMinutes(time),
TimeUnit.SECONDS.toSeconds(time) % TimeUnit.MINUTES.toSeconds(1));
System.out.println(String.format("%d : %s", time, result));
}
Outputs
360000 : 6000:00
3000 : 50:00
4350 : 72:30
36300 : 605:00
0 : 0:00
Just ditch the hours bit.
return String.format("%04d:%02d",
TimeUnit.SECONDS.toMinutes(seconds),
TimeUnit.SECONDS.toSeconds(seconds) % TimeUnit.MINUTES.toSeconds(1));
public static String formatChronometer(long seconds) {
Duration dur = Duration.ofSeconds(seconds);
return String.format("%02d:%02d", dur.toMinutes(), dur.toSecondsPart());
}
When I fed 36005 into this method, it returned 600:05.
I take it that your chronometer seconds denote a duration, an amount of time. Either an elapsed time or a value to count down from. Not a time of day (you mentioned 100 hours an example, but the time of day is never 100 hours). In that case I would clearly use the Duration class for modelling it. It’s the most correct thing to do. Some use the word self-documenting about code written with such a consideration in mind.
The Duration.toSecondsPart method was only introduced in Java 9. If you are using Java 8 (or Java 6 or 7 with the ThreeTen Backport), get the seconds part by subtracting the minutes and then converting to seconds:
long minutes = dur.toMinutes();
dur = dur.minusMinutes(minutes);
return String.format("%02d:%02d", minutes, dur.toSeconds());
Then the result is the same.
PS If your seconds denoted a time-of-day instead, the correct and self-documenting solution would be to use the LocalTime class:
LocalTime chrono = LocalTime.ofSecondOfDay(seconds);
return String.format("%02d:%02d",
chrono.get(ChronoField.MINUTE_OF_DAY), chrono.getSecond());
This will reject seconds values greater than 86399 with an exception since the time of day cannot be 24:00 or greater.
Remove your hours from the formatting
public static String formatChronometer(long seconds) {
return String.format("%02d:%02d",
TimeUnit.SECONDS.toMinutes(seconds),
TimeUnit.SECONDS.toSeconds(seconds) % TimeUnit.MINUTES.toSeconds(1));
}
Related
I have seen this code on stackoverflow but I don't understand how it works, I feel so frustrated
new CountDownTimer(9000000, 1000) {
public void onTick(long millisUntilFinished) {
long millis = millisUntilFinished;
String time = String.format("%02d:%02d:%02d",
// From here,, I don't understand what is "going on "
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis)-
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis)-
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
}
9000000 milliseconds is : 02:30:00
Hour : TimeUnit.MILLISECONDS.toHours(millis),
9000000 milliseconds to hours is : 2,5 hours
Up to this, it's gonna show : 02:00:00
OK, I get it
Minutes : TimeUnit.MILLISECONDS.toMinutes(millis)- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
I've converted and soustracted :
TimeUnit.MILLISECONDS.toMinutes(millis) = 150
TimeUnit.MILLISECONDS.toHours(millis) = 2,5
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)) = 150
150-150 = 0 , shouldn't I have something equal to 30 ??
Seconds : TimeUnit.MILLISECONDS.toSeconds(millis)-TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
Same thing, it's gonna give me 0
How does this work ? Thank you
}
Try doing it manually. First work out how many whole hours. Then subtract the number of whole hours (in milliseconds) from the total milliseconds and use that result to calculate then number of whole minutes. You can do the same for seconds (but to get the number of seconds, it’s ok to simply subtract off the whole minutes because there’s a whole number of minutes in a hour so the hours are automatically handled).
Maybe dummy variables would help:
WholeHours = TimeUnit.MILLISECONDS.toHours(millis)
WholeMinutes = TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
WholeSeconds = TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
I am using System.currentTimeMillis() to get number of milliseconds since 1970, I can get current Hour, Minute and seconds using following:
Long currTimeInMilliSec = System.currentTimeMillis()
int h = (((currTimeInMilliSec / 1000) / 3600 ) % 24)
int m = (((currTimeInMilliSec / 1000) / 60) % 60)
int s = ((currTimeInMilliSec / 1000) % 60)
How can I calculate millisecond of Current time (not from 1970), because if I use int ms = currentTimeInMilliSec that would be number of milliseconds since 1970.
Note: For some reason, I need to use only currentTimeMillis function to calculate and I don't want to use other functions or external libraries.
Use currentTimeInMilliSec % 1000.
You can also think about it this way: it works for the same reason that int m = totalMinutes % 60 works, and you have already found that this works.
But a more detailed explanation is as follows: N % M gives you a number from 0 to M - 1. So, you will always get a number of milliseconds from 0 to 999. And each time your currentTimeInMilliSec advances by one, this number also advances by one, but if this number ever exceeds 999, it warps around to 0, which is the exact behaviour that you want.
This question is about arithmetics and not programming, but here:
Given a specific time t, the number of ms from t to current time is:
System.currentTimeMillis() + ([midnight, January 1, 1970 UTC] - t).
Now all you have to do is decide on a unit of measurement and convert all the abstractly represented times aboves to it and perform the calculation.
Example:
If t is midnight, January 1, 1960 UTC, then
[midnight, January 1, 1970 UTC] - t = [number of ms in 10 years]
and the number of ms from t to now is
System.currentTimeMillis() + [number of ms in 10 years].
I'm having Minutes in java.lang.Long and want to convert this value to java.math.BigDecimal, ie. as Hours.
BigDecimal hours = BigDecimal.valueOf(minutes)
.divide(BigDecimal.valueOf(DateTimeConstants.MINUTES_PER_HOUR))
.setScale(2,RoundingMode.HALF_DOWN);
Tried the above method. It return hours, but no the way actually i want it
How i need is :
240 Minutes : 4 Hours
230 Minutes : 3.50 hours
Any help?
I would convert your Minutes to a Period object:
Minutes minutes = ...;
Long millisec = minutes*60*1000;
Period period = new Period(millisec);
Then use the Period object you can ask the Hours. Anything you want...
Note: 230 minutes is not 3.50 hours, it's 3.83 hours, i'm assuming you mean "3 hours and 50 minutes".
So what you want is the hh:mm representation.
You don't need BigDecimals. Use this:
long minutes = 230;
long hours = minutes / 60;
long minnutesRemaining = minutes % 60;
System.out.println(hours + "." + minnutesRemaining);
I'm betting the OP actually wants to convert minutes into hours and minutes. This is as easy as:
int minutes = 230;
System.out.println(
String.format("%d Minutes: %d:%02d Hours", minutes, (minutes/60), (minutes%60)));
Just printing the minutes divided by 60 (using integer arithmetic) and the modulo of minutes divided by 60 (formatted as two digits with leading zeros by the "%02d" format.
You can do this using BigDecimal easy. You can use divideAndRemainder()
long minutes = 230L;
BigDecimal min = new BigDecimal(minutes);
BigDecimal constant = new BigDecimal(60);
BigDecimal[] val=min.divideAndRemainder(constant);
System.out.println(val[0]+"."+val[1]+" Hours");
Out put:
3.50 Hours
I don't know in what universe 230 minutes equals 3.5 hours, so I'm afraid that some string manipulation is your best bet:
BigDecimal hours = new BigDecimal(
String.format("%d.%d", minutes / 60, minutes % 60));
Printing out the value of hours yields 3.50, as per your requirement.
Use integer and modulo arithmetic:
long hours = minutes / 60; /*implicit round-down*/
long numberAfterDecimal = (minutes % 1.0 /*pull out the remainder*/) * 60;
Then format these two numbers as you wish.
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.
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.