This question already has answers here:
LocalTime() difference between two times
(2 answers)
Closed 3 years ago.
I've looked at just about all the other posts pertaining to my question without finding a similar issue as mine.
I'm trying to get the time between two fields using this code.
LocalTime timeFrom = LocalTime.parse("16:00");
LocalTime timeTo = LocalTime.parse("00:00");
System.out.println(Duration.between(timeFrom,timeTo).toHours());
The issue I'm having is that the print out is negative 16 hours. What I want to accomplish is to get the amount of time from 4pm (which is 1600) to 12am (which is 00:00).
The result that I'm looking for would be 8 hours.
I have an idea of taking 1 minute from the 00:00, then getting the duration between those then just simply adding the 1 minute back to it, but I was thinking there must be an easier way.
After pondering I feel like I was looking for a programmer solution instead of a simple one...
The answer to this is just adding 24 hours back to the negative result!
LocalTime timeFrom = LocalTime.parse("16:00");
LocalTime timeTo = LocalTime.parse("00:00");
long elapsedMinutes = Duration.between(timeFrom, timeTo).toMinutes();
//at this point Duration for hours is -16.
//checking condition
if(timeTo.toString().equalsIgnoreCase("00:00")){
//condition met, adding 24 hours(converting to minutes)
elapsedMinutes += (24 * 60);
}
long elapsedHours = elapsedMinutes / 60;
long excessMinutes = elapsedMinutes % 60;
System.out.println("Hours: " + elapsedHours);
System.out.println("Minutes: " + excessMinutes);
I propose to check if the result is negative, then you don't limit the code to check for exact string equality, and 00:01 will still come out 8 hours:
import java.time.Duration;
import java.time.LocalTime;
public class StackOverflowTest {
public static void main(String[] args) {
String from = "16:00";
String to = "00:01";
LocalTime timeFrom = LocalTime.parse(from);
LocalTime timeTo = LocalTime.parse(to);
Duration duration = Duration.between(timeFrom,timeTo);
if (duration.isNegative()) duration = duration.plusDays(1);
System.out.println(duration.toHours());
}
/*
Prints:
8
*/
}
Or perhaps or more reader-friendly option:
...snip
Duration duration;
if (timeFrom.isBefore(timeTo)) {
duration = Duration.between(timeFrom,timeTo);
} else {
duration = Duration.between(timeFrom,timeTo).plusDays(1);
}
Related
This question already has answers here:
Java 8: Difference between two LocalDateTime in multiple units
(11 answers)
Closed 2 years ago.
I decided to give myself a challenge on Java that implements this question's achievement.
The things I have to do is get LocalDateTime, convert the same code from the linked question's answers, then receiving a string from the function.
Here's what I've done so far:
public static String relTime(LocalDateTime now)
{
// accepted answer converted to Java
const int min = 60 * SECOND;
const int hour = 60 * MINUTE;
const int day = 24 * HOUR;
const int mon = 30 * DAY;
// still don't know how to convert this method
var ts = new TimeSpan(DateTime.UtcNow.Ticks - yourDate.Ticks);
double delta = Math.Abs(ts.TotalSeconds);
if (delta < 1 * MINUTE)
return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
if (delta < 2 * MINUTE)
return "a minute ago";
if (delta < 45 * MINUTE)
return ts.Minutes + " minutes ago";
if (delta < 90 * MINUTE)
return "an hour ago";
if (delta < 24 * HOUR)
return ts.Hours + " hours ago";
if (delta < 48 * HOUR)
return "yesterday";
if (delta < 30 * DAY)
return ts.Days + " days ago";
if (delta < 12 * MONTH)
{
int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
return months <= 1 ? "one month ago" : months + " months ago";
}
else
{
int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
return years <= 1 ? "one year ago" : years + " years ago";
}
}
The only problem that I should encounter is from var ts = new TimeSpan(DateTime.UtcNow.Ticks - yourDate.Ticks);.
Although I read 2 questions from Stack Overflow finding equivalents of TimeSpan and Ticks, I baely have any ideas how to properly convert the line of code. Also, I have to get a double which will need math.abs() to get TotalSeconds which I can't really find a proper way to deal with either, but I did find ZoneOffset.ofTotalSeconds and still don't know how to deal with it.
So how can I convert this properly?
var ts = new TimeSpan(DateTime.UtcNow.Ticks - yourDate.Ticks);
double delta = Math.Abs(ts.TotalSeconds);
You need to gain a deeper understanding of what this method actually does. Literally translating code from C# to Java won't give you a good solution and gets you stuck on language-specific details.
The two lines basically calculate the (absolute) difference in seconds of a timestamp to the current time. This can be written in Java as follows:
Duration duration = Duration.between(LocalDateTime.now(), timestamp);
long delta = duration.abs().getSeconds();
I'm just addressing your actual question here on how to transform these two lines. The provided snippet is not valid Java code and some parts are missing. delta is the difference in seconds which does not necessarily need to be a double. The argument you pass to your method should be named anything else than now because this is the timestamp you want to compare to the current time inside the method.
You could use SimpleDateFormat to create a nice display format (use something like "HH hours, mm minutes and ss seconds ago" for the format (not sure if this exact example works)). You could also use Instant to get the current time, and you can use Instant.now().minusSeconds(Instant.now().minusSeconds(seconds).getEpochSeconds()) for the time difference (or just use System.currentTimeMillis() and multiply by 1000).
Alternatively, you could use Duration and write a custom display format using getSeconds() and getHours() etc.
This question already has answers here:
Java 8: Difference between two LocalDateTime in multiple units
(11 answers)
Closed 3 years ago.
I tried this code:
public class TimePassed {
private long seconds;
private long minutes;
private long hours;
private long days;
private long years;
...
public TimePassed(double unixSeconds) {
Instant now = Instant.now();
Instant ago = Instant.ofEpochSecond((long) unixSeconds);
this.seconds = ChronoUnit.SECONDS.between(
ago.atZone(ZoneId.systemDefault()),
now.atZone(ZoneId.systemDefault())); //6100
this.minutes = ChronoUnit.MINUTES.between(
ago.atZone(ZoneId.systemDefault()),
now.atZone(ZoneId.systemDefault())); //101
this.hours = ChronoUnit.HOURS.between(
ago.atZone(ZoneId.systemDefault()),
now.atZone(ZoneId.systemDefault())); //1
this.days = ChronoUnit.DAYS.between(
ago.atZone(ZoneId.systemDefault()),
now.atZone(ZoneId.systemDefault())); //0
this.years = ChronoUnit.YEARS.between(
ago.atZone(ZoneId.systemDefault()),
now.atZone(ZoneId.systemDefault())); //0
}
}
However then the TimePassed object would have seconds = 6100 and minutes = 101 and hours = 1, while I want it to be hours = 1, minutes = 41, seconds = 40, so that 60*60 + 41*60 + 40 = 6100. Is it possible to do with java.time package? Because as of now I can only either get passed seconds, passed minutes or passed hours, etc. And neither would account for the other.
Java 9 answer: Duration.toXxxPart methods
Basic idea, not complete:
Duration dur = Duration.between(ago, now);
this.seconds = dur.toSecondsPart(); // 40
this.minutes = dur.toMinutesPart(); // 41
this.hours = dur.toHoursPart(); // 1
this.days = dur.toDaysPart(); // 0
Tested with instants that are 6100 seoncds apart like yours from the question. The toXxxPart methods were introduced in Java 9. For Java 8 (or ThreeTen Backport) you will need to start from the coarser units, the days, and subtract them from the duration before getting the next finer unit. See this answer by lauhub for an example
The years and days are a bit tricky to get completely correct, though. To get only the days that exceed the whole years here’s the full code:
ZoneId zone = ZoneId.systemDefault();
ZonedDateTime agoZdt = ago.atZone(zone);
ZonedDateTime nowZdt = now.atZone(zone);
this.years = ChronoUnit.YEARS.between(agoZdt, nowZdt);
ZonedDateTime afterWholeYears = agoZdt.plusYears(this.years);
Duration dur = Duration.between(afterWholeYears, nowZdt);
this.seconds = dur.toSecondsPart(); // 40
this.minutes = dur.toMinutesPart(); // 41
this.hours = dur.toHoursPart(); // 1
this.days = dur.toDays(); // 0
I am on purpose reading ZoneId.systemDefault() only once just for the unlikely case that someone changes the default time zone setting underway.
Something like this should work:
ZoneId zone = ZoneId.systemDefault();
ZonedDateTime ago = ZonedDateTime.ofInstant(Instant.ofEpochSeconds(unixSeconds), zone);
ZonedDateTime now = ZonedDateTime.now(zone);
Period period = Period.between(ago.toLocalDate(), now.toLocalDate());
ZonedDateTime adjusted = ago.with(now.toLocalDate());
if (adjusted.isAfter(now)) {
adjusted = adjusted.minusDays(1);
period = period.minusDays(1);
}
Duration duration = Duration.between(adjusted, now);
assert duration.toDaysPart() == 0;
years = period.getYears();
months = period.getMonths();
days = period.getDays();
hours = duration.toHoursPart();
minutes = duration.toMinutesPart();
seconds = duration.toSecondsPart();
Why/how this works:
The difference in non-time fields (year, month, day) is computed by using a specialized Period type, which is intended exactly for this purpose. It uses LocalDate part of two date-times, which is safe, since they are both in the same time zone
To know the difference in rest of the fields, we adjust the "ago" value, so that the days are exactly the same. If we happened to overshoot (which might happen if "ago" happened at earlier local time compared to "now"), we adjust to that by decreasing both the adjusted date-time and also the period by one day
Then, we use Duration class to get the difference between time-based fields. Since there we query the difference between adjusted date-times, our duration will not be more than one day, to which I added the assertion for.
Lastly, I used various methods available on both Period and Duration to obtain their "fields". Note that methods of Duration class that I used only available since Java 9, so if you don't have it yet, you'll have to use methods like toMinutes() and manually divide them by amount of, for example, minutes per hour and such:
// those constants you'll have to define on your own, shouldn't be hard
hours = duration.toHours() % Constants.HOURS_PER_DAY;
Alternatively, if you don't want to define constants, you can repeat the trick with adjusting the "ago" variable:
adjusted = ago.with(now.toLocalDate());
if (adjusted.isAfter(now)) {
adjusted = adjusted.minusDays(1);
period = period.minusDays(1);
}
hours = HOURS.between(adjusted, now);
adjusted = adjusted.withHour(now.getHour());
if (adjusted.isAfter(now)) {
adjusted = adjusted.minusHour(1);
hours -= 1;
}
minutes = MINUTES.between(adjusted, now);
adjusted = adjusted.withMinute(now.getMinute());
if (adjusted.isAfter(now)) {
adjusted = adjusted.minusMinutes(1);
minutes -= 1;
}
seconds = SECONDS.between(adjusted, now);
This question already has answers here:
How to calculate "time ago" in Java?
(33 answers)
Closed 7 years ago.
I want to display how long ago something happened. For example
24 minutes ago //discard seconds
3 hours ago //discard minutes
5 days ago // discard hours
3 weeks ago // discard days
All I have is a long timestamp and so I am free to use java.util.Date or jodatime or whatever other Time android uses. I am having such a hard time getting it right. I try to use jodatime with minus but I can't quite get the right answer yet.
One approach is for me to do the whole thing myself: first subtract my timestamp from now and then do some arithmetics. But I would rather avoid that route if possible.
Android provides the utility class DateUtils for all such requirements. If I've understood your requirement correctly, you need to use the DateUtils#getRelativeTimeSpanString() utility method.
From the docs for
CharSequence getRelativeTimeSpanString (long time, long now, long minResolution)
Returns a string describing 'time' as a time relative to 'now'. Time spans in the past are formatted like "42 minutes ago". Time spans in the future are formatted like "In 42 minutes".
You'll be passing your timestamp as time and System.currentTimeMillis() as now. The minResolution specifies the minimum timespan to report.
For example, a time 3 seconds in the past will be reported as "0 minutes ago" if this is set to MINUTE_IN_MILLIS. Pass one of 0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS
You can use the following code :
public class TimeAgo {
public static final List<Long> times = Arrays.asList(
TimeUnit.DAYS.toMillis(365),
TimeUnit.DAYS.toMillis(30),
TimeUnit.DAYS.toMillis(1),
TimeUnit.HOURS.toMillis(1),
TimeUnit.MINUTES.toMillis(1),
TimeUnit.SECONDS.toMillis(1) );
public static final List<String> timesString = Arrays.asList("year","month","day","hour","minute","second");
public static String toDuration(long duration) {
StringBuffer res = new StringBuffer();
for(int i=0;i< Lists.times.size(); i++) {
Long current = Lists.times.get(i);
long temp = duration/current;
if(temp>0) {
res.append(temp).append(" ").append( Lists.timesString.get(i) ).append(temp > 1 ? "s" : "").append(" ago");
break;
}
}
if("".equals(res.toString()))
return "0 second ago";
else
return res.toString();
}
}
Just call the toDuration() method with your long timestamp as parameter.
You can also use DateUtils.getRelativeTimeSpanString() . You can read the documentation here Date Utils
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
i want learn remaining time from current time to 18.30
My code is not working:
long currentTime = System.currentTimeMillis();
long endTime = 18:30;
long remaining = endTime - currentTime;
long hours = remaining / 3600000;
long mins = remaining / 60000 % 60;
long seconds = remaining / 1000 % 60;
String remainingText = String.format("%02d:%02d:%02d", hours,mins,seconds);
long endBidTime = ();
As you know, this causes a compiler error. From the comments, you seem to want to set this to 18:30 on the current day. One solution is to use the Date object. You will first need to create a Date object and set its time to 18:30. See the javadocs for the Date class for details about how to do this. You will also need to use Date.currentTimeMillis() to get the correct value for endBidTime.
You have another problem in your code:
String remainingText = "%02d:%02d:%02d".format(hours,mins,seconds);
This is incorrect and probably gives other compiler errors. Note that the format() method is static. Even though Java allows us to call static method with an instance variable, it is strongly discouraged. Instead, you should use the class name. Also, the format string is the first parameter that format() expects. This means you should do the following:
String remainingText = String.format("%02d:%02d:%02d", hours,mins,seconds);
currentTimeMillis() returns the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC. See here.
If you want to find the remaining time left till today 18:30. You have to first find the time in milliseconds at today 18:30 (then find the difference), here is my code:
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import static java.util.concurrent.TimeUnit.*;
public class timetill1830 {
public static void main(String[] args) {
int hr = 18, min = 30, sec = 0;
Calendar calendar = Calendar.getInstance();
//Now set the time for today 18:30
Calendar cal = new GregorianCalendar(calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH), hr, min, sec);
System.out.println(cal.getTimeInMillis());
System.out.println(System.currentTimeMillis());
// Now Print time left till 18:30
System.out.println("Time in millsec. till 18:30 = "
+ (cal.getTimeInMillis() - System.currentTimeMillis()));
formattedTimeLeft(cal.getTimeInMillis() - System.currentTimeMillis());
}
private static void formattedTimeLeft(long millis) {
int hrs = (int) (MILLISECONDS.toHours(millis) % 24);
int min = (int) (MILLISECONDS.toMinutes(millis) % 60);
int sec = (int) (MILLISECONDS.toSeconds(millis) % 60);
//int mls = (int) (millis % 1000);
System.out.println("Time left "+hrs+" hours "+min+" minutes "+sec+" seconds");
}
}
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.