I need to calculate the time passed between two dates.
The catch here is that I need to show it as YouTube does with its video comments timestamps. That is, to show it by just the largest measure.
For example,
if the time is 50 seconds ago it should say 50 seconds ago.
if the time is more than one minute it should say one minute ago/ten minutes ago etc..
if the time difference is 1 hour 30 mins it should show: an hour ago.
if the time is one and a half week than it should say one week ago.
if the time is more than a month it should say one month ago/two months ago etc...
and so on and so on..
So what is the best way to handle this?
Should I make a method with case or if statements that would return something like this? Or is there a better approach (maybe a library which already does something like it)?
Use DateUtils.getRelativeTimeSpanString(long time, long now, long minResolution). time is the start time, and now is the end time (in milliseconds). To report "seconds ago," set minResolution to zero.
Example:
String result = DateUtils.getRelativeTimeSpanString(1306767830, 1306767835, 0);
// result = "5 seconds ago"
date1.getTime() - date2.getTime()
This will return you the time in miliseconds between the 2 dates. Just convert that to what ever you want to show (e.g. hours minutes seconds)
On Android, use this: http://developer.android.com/reference/android/text/format/DateUtils.html#getRelativeTimeSpanString%28android.content.Context,%20long,%20boolean%29
Take a look at PrettyTime!
Also, everytime you want to do something date/time-related in Java, you should take a look at Joda Time. Do it now, you will thank me later.
Your need is very specific, and I don't know any lib that would solve the problem for you out of the box.
However the problem is not very complex and a small function full of "ifs" should do the trick.
Of course, a nice date library like Joda Time will help you keep your code clean. Who wants to use GregorianCalendar!?
Looks like you have a set of custom rules and the algorithm to choose a rule is based on the time in seconds between two timestamps. The easiest approach is to handle the rules in a series of if/else if statements:
private String getTimeAsString(int seconds) {
if (seconds < 60) { // rule 1
return String.format("%s seconds ago", seconds);
} else if (seconds < 3600) { // rule 2
return String.format("%s minutes ago", seconds/60);
} // ... and so on
}
Related
Problem situation: I have an incredibly high number of records all marked with a timestamp. I'm looping through all of them to do this and that but I need to detect when the day has changed.
Right now for each loop I'm doing:
cal.setTimeInMillis(record.time);
int currentDay = cal.get(Calendar.DAY_OF_WEEK);
Is this as slow as I imagine it is when it's running hundreds of thousands of times?
I imagine I'm missing a really simple modulo answer or something.
Edit: Time zone does not matter, the information I'm collecting more resolves around a consumable report for someone. 24 hours per report is more accurate, so realistically I don't have to worry about whether or not that's 5am - 5am or 3pm - 3pm, just that I was able to gather 24H worth of info.
Thanks all
After Andy Turner’s time test I am not necessarily convinved that you need any optimized solution. In any case, timsmelik’s suggestion is pretty straightforward: convert the time when the day changes to a count of milliseconds since the epoch so you only need to compare long values. I don’t find that it hurts readability very badly. So here it is in code. I am using and warmly recommending java.time, the modern Java date and time API, if only for the conversion from hours to milliseconds and for printing the results. Even when such a conversion seems trivial, it’s always best to leave to the standard library to do it. It’s more self-explanatory and less error-prone, and it’s easier for the reader to convince oneself that it’s correct.
final long twentyfourHoursAsMillis = Duration.ofHours(24).toMillis();
// Times are already sorted descending (from newest to oldest)
long[] times = { 1_611_718_370_000L, 1_611_632_000_000L,
1_611_631_970_000L, 1_611_459_150_000L };
List<List<Long>> chunks = new ArrayList<>();
List<Long> currentChunk = new ArrayList<>();
// Process first time separately to get started
currentChunk.add(times[0]);
long timeOfNextChunk = times[0] - twentyfourHoursAsMillis;
// Process remaining times
for (int i = 1; i < times.length; i++) {
long currentTime = times[i];
if (currentTime <= timeOfNextChunk) {
chunks.add(currentChunk);
currentChunk = new ArrayList<>();
do {
timeOfNextChunk -= twentyfourHoursAsMillis;
} while (currentTime <= timeOfNextChunk);
}
currentChunk.add(currentTime);
}
// Save last chunk, why not?
chunks.add(currentChunk);
// Print result
for (List<Long> chunk : chunks) {
String chunkAsString = chunk.stream()
.map(Instant::ofEpochMilli)
.map(Instant::toString)
.collect(Collectors.joining(", "));
System.out.println(chunkAsString);
}
Output is:
2021-01-27T03:32:50Z, 2021-01-26T03:33:20Z
2021-01-26T03:32:50Z
2021-01-24T03:32:30Z
I am printing Instant objects. They always print in UTC. For your situation you may want to do otherwise if you need to print the times at all.
You should add a check of your assumption that the times come in sorted order.
I have taken your word for it and broken into chunks at 24 hours. 24 hours may not even mean 5am - 5am but could mean for instance from 5 AM EST on March 13 to 6 AM EDT on March 14 because summer time (DST) has begun in the meantime. If you prefer to split at the same clock hour, the code can be modified to do that.
I'm trying to setup my addToDay function. I'm currently stuck on how to proceed with this or even write it correctly. The function itself will take a variable that ranges from -100 to 100. So you would basically add that variable to the current and if it was below the 0 then subtract a month or if it was above the months max day then add a month. Which i have that function setup so all i would have to do is call addToMonth with the correct amount. My problem lies within the amount of days each month has. For example, October has 31 days while November has 30. I have a function that will return the number of days in the current set month so i can call that to get how many max days should be in the current month. I'm thinking maybe a while loop would work but i just wanted to get anyone's thoughts on the best way to set it up.
I have 3 private ints: month, day, year. These are what need to be changed. I have both addTo functions for month and year setup already.
Here are some other functions i have created that can be used in this:
1. addToMonth(int delta) - changes the current month depending on the given parameter
2. getDaysInMonth() - will return the days in a month depending on the month itself
3. validateDay() - Will return true or false if the days fall outside the wanted requirements.
I don't want to use the calendar utility
I also don't want to use any other utilities. Just the base code with Junit for testing
Joda's plusDays() function and Java 8 LocalDate already has the logic that you are trying to achieve
Alright so i ended up just copying my original addToMonth function and modifying it abit to fit with days. So far it works but i do think it'll fail in the cases of different amounth of days not lining up.
I have a chronometer used as a timer in a game. Currently it only shows seconds (by default). I have been trying to get the format to show in minutes:seconds:milliseconds. I tried but nothing is working. Here is the code I found on StackoverFlow that says it should work...but didn't. OR if you have any other solutions instead of chronometer please let me know! (This is in android, using java)
-Thanks
Chronometer chronometer;
chronometer.setFormat(MM:SS:mm);
Actually, there's a much nicer way of doing this:
void OnGUI() {
int minutes = Mathf.FloorToInt(timer / 60F);
int seconds = Mathf.FloorToInt(timer - minutes * 60);
string niceTime = string.Format("{0:0}:{1:00}", minutes, seconds);
GUI.Label(new Rect(10,10,250,100), niceTime);
}
This will give you times in the 0:00 format. If you'd rather have 00:00, simply do
string niceTime = string.Format("{0:00}:{1:00}", minutes, seconds);
There's a couple of possibilities you have with the formats here: {0:#.00} would give you something like 3.00 or 10.12 or 123.45. For stuff like scores, you might want something like {0:00000} which would give you 00001 or 02523 or 20000 (or 2000000 if that's your score ;-) ). Basically, the formatting part allows any kind of formatting (so you can also use this to format date times and other complex types). Basically, this means {indexOfParameter:formatting}
I am looking to calculate the number of minutes given the time of the day.
Eg.: when input is 11:34, the output should be 11*60+34. The date doesn't matter.
I only need it down to the minutes scale. Seconds, milliseconds... don't matter.
Is there a method somewhere in Java doing this the neat way without me calculating it?
Right now, i'm using theTime.split(":"), theTime is a String holding "11:34" here, parsing the integers on each side and doing the calculation.
I saw Time but what I'm doing right now seemed more direct.
Nothing in Systems either.
There is no build in method for it. However here is a one-liner for it:
int timeInMins = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) * 60 + Calendar.getInstance().get(Calendar.MINUTE);
Your approach looks good and sound, however to answer your question it would be simple to say that there is no such build in method which does that. You have to calculate it the way you are doing it right now.
Hi maybe you could use JodaTime? Below example how to get number of minutes from parsed string and from current time. In java 8 there is similar api but I haven't found exactly method like minutesOfDay()
#Test
public void learnHowManyMinutesPassedToday() {
DateTime time = DateTimeFormat.forPattern("HH:mm").parseDateTime("11:34");
System.out.println(time.getMinuteOfDay());
System.out.println(DateTime.now().getMinuteOfDay());
}
If you are looking to have input not from a String, take a look at
Java.util.Calendar.
It has Calendar.HOUR_OF_DAY and Calendar.HOUR and Calendar.MINUTE which could be your input. I'm not sure what the "neat" way of doing this would be. It is a simple calculation.
Calendar rightNow = Calendar.getInstance();
int hour = rightNow.get(Calendar.HOUR);
int min = rightNow.get(Calendar.MINUTE);
System.out.println("TimeMinutes:" + hour * 60 + min);
EDIT:
Except using split use the above.
Quick question:
I´m having an Interval of one day:
Interval interval = new LocalDate().toInterval(DateTimeZone.getDefault());
Suppose I want to add one day at the beginning and one day at the end.
Right now I use the methods withDurationBeforeEnd and withDurationAfterStart which don´t really fit to my use case. Am I missing something? I was looking for some API like Interval.addPeriod(Period period);
Or am I completely wrong and should use something else?
Interval newInterval = new Interval(oldInterval.getStart().minusDays(1), oldInterval.getEnd().plusDays(1));