We're using MySQL to store some dates. I'm looking to show these as relative time periods in the user interface: 2 hours ago, 3 days ago etc. (Like Twitter does for the updates for example)
Is there a well-known way to accomplish this, or should I get creative with it?
Just to be clear, I want to transform:
07/26/2009 12:20 -> '2 days ago'
As I understand your problem, the "Human Time" class is a solution.
check Date Formatting and Parsing for Humans in Java with HumanTime
.
I would take a look at the Joda library for performing this type of date-time arithmetic. For example, you could create a Joda Duration and then convert it to a Period, giving you access to numerous useful methods:
ResultSet rs = ...
Date dbDate = rs.getDate("Date"); // Get stored time in database.
long serverTime = System.currentTimeMillis(); // Get current server time.
// Compute absolute difference between two time-stamps.
Duration duration = new Duration(Math.abs(serverTime - dbDate.getTime()));
// Convert to period and make use of getHours(), getMinutes(), etc for display purposes.
Period period = duration.toPeriod();
System.err.println("Hours: " + period.getHours());
System.err.println("Minutes: " + period.getMinutes()); // etc.
The Java standard API method for date calculations is Calendar.add() (which also takes negative parameters).
I think the most common solution is to convert it to unix timestamps (or equivalent, milliseconds in Java normally), take the difference and start dividing away.
time = now - then;
time /= 1000; /* if milliseconds... */
seconds = time % 60; time /= 60;
minutes = time % 60; time /= 60;
hours = time % 60; time /= 60;
days = time % 24; time /= 24;
weeks = time % 7; time /= 7;
or months (although, then it starts to get tricky...), or whatever you want to use.
Have fun.
My advice is run your server in UTC and then use JodaTime to do any date arithmetic or conversion between timezones.
There's considerably more to date arithmetic than meets the eye once you factor in things like DSL, leap-seconds, convention changes, etc and it's really the last thing you want to be doing yourself.
The question is rather vague.
In Java, using JodaTime Date API;
3 days ago:
DateTime date = new DateTime();
DateTime threeDA = date.plusDays(-3);
int daysBetween = Days.daysBetween(dbDate, threeDA).getDays();
int monthsBetween = Months.monthsBetween(dbDate, threeDA).getMonths();
or you could use the JodaTime Period/Duration objects.
In MySQL, use a built-in MySQL Date Function e.g.:
SELECT SUBTIME(SYSDATE(),'3'); -- untested, no MySQL to hand
SELECT SUBTIME('2007-12-31 23:59:59.999999','3 0:0:0.000000');
For date differences:
SELECT DATEDIFF(columnname, SYSDATE()); -- Days since
SELECT TIMEDIFF(columnname, SYSDATE()); -- Time since
In Java, using Gregorian Calendar:
GregorianCalendar threeDA = new GregorianCalendar();
threeDA.add(GregorianCalendar.DAY_OF_YEAR, -3);
If you can use java for the conversion, have a look at the Joda library.
On the MySQL side:
CONVERT('date-time-value-here', DATETIME) - NOW()
Related
How to parse date time from double to datetime in java? In c# it is ok from this post
Suggest for parsing in java?
Example:
44233.8647553819// --> date: 2021-02-06 20:45:14
The problem is, this mechanism of storing a time stamp is silly, and C# allows it by mixing up different conceptions of time. It does what you evidently want, but that's not a good thing - those kinds of APIs make it easy to make mistakes.
In java, the same API exists, but only allows you to specify an integral number of days - thus, you can't save your .8647553819 part - you'd have to apply that directly.
But that's not possible without answering some more questions about where on the planet you are.
Let's start with just the days part:
double raw = 44233.8647553819;
long days = (long) raw;
double fraction = raw - days;
LocalDate epoch = LocalDate.of(1899, 12, 30);
LocalDate date = epoch.plusDays(days);
System.out.println(date);
> 2021-02-06 - so far, so good
Now turning .8647553819 into a specific time is much more convoluted. What if that date is a day with only 23 hours? What if it has 25 hours? This representation system can't deal with any of this, and it also has issues with accuracy; doubles are optimized for accuracy and not speed. So, this is a best effort basis kinda deal
double maxSeconds = LocalTime.MAX.toSecondOfDay();
int seconds = (int) (maxSeconds * fraction);
LocalTime time = LocalTime.ofSecondOfDay(seconds);
LocalDateTime stamp = date.atTime(time);
System.out.println(stamp);
> 2021-02-06T20:45:14
I can't stress enough that this is a silly system, but, there you have it.
I'm having an issue working with time in Java. I don't really understand how to efficiently solve comparing the time of now and 12 hours before and after
I get a set of starting times for a show from an API and then compare that starting time with LocalTime.now(). It looks something like this:
SimpleDateFormat sdt = new SimpleDateFormat("HH:mm:ss");
String temp = sdt.format(Local.time(now));
LocalTime secondTime = LocalTime.parse(parts1[0]);
LocalTime firstTime = LocalTime.parse(temp);
int diff = (int) ((MINUTES.between(firstDay, secondDay) + 1440) % 1440);
if(diff <= 720){
return true;
}
Where my idea is that if the difference between the two times is smaller than 720 minutes (12 hours) I should get the correct output. And this works for the 12 hours before now. I thought I might need to swap the parameters of .between, to get the other side of the day. That counts it completely wrong (If the time now is 15:00:00 it would accept all the times until 22:00:00 the same day). Is this just a really bad way of comparing two times? Or is it just my math that lacks understanding of what I'm trying to do?
Thanks
Using the 'new' (not that new) Java 8 time API:
Instant now = Instant.now();
Instant hoursAfter = now.plus(12, ChronoUnit.HOURS);
Instant hoursBefore = now.minus(12, ChronoUnit.HOURS);
First, doing this kind of operations on java.time.LocalTime won't work! Or at least only if the time is "12:00:00" …
That is because you will have an over-/underflow when you add/substract 12 hours from any other time.
So your starting point should be to go for java.time.LocalDateTime (at least, although I would go for java.time.Instant). Now you can handle the over-/underflow, as you will get another day when adding or subtracting 12 hours.
How this works is shown in this anwswer: LocalDateTime allows nearly the same operations as Instant.
I am working on a project in my CIS 163 class that is effectively a campsite reservation system. The bulk of the code was provided and I just have to add certain functionalities to it. Currently I need to be able to determine how much time has passed between 2 different GregorianCalendar instances (one being the current date, the other being a predetermined "check out") represented by days. I haven't been able to figure out quite how to do this, and was hoping someone here might be able to help me out.
The GregorianCalendar is old and you shouldn't really use it anymore. It was cumbersome and was replaced by the "new" java.time module since Java 8.
Still, if you need to compare using GC instances, you could easily calculate time using milliseconds between dates, like this:
GregorianCalendar date1 = new GregorianCalendar();
GregorianCalendar date2 = new GregorianCalendar();
// Adding 15 days after the first date
date2.add(GregorianCalendar.DAY_OF_MONTH, 15);
long duration = (date2.getTimeInMillis() - date1.getTimeInMillis() )
/ ( 1000 * 60 * 60 * 24) ;
System.out.println(duration);
If you want to use the new Time API, the following code would work.
LocalDate date1 = LocalDate.now();
LocalDate date2 = date1.plusDays(15);
Period period = Period.between(date1, date2);
int diff = period.getDays();
System.out.println(diff);
If you need to convert between the types (e.g. you're working with legacy code), you can do it like this:
LocalDate date3 = gcDate1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate date4 = gcDate2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
Also I'm pretty sure this question must've been asked over and over again, so make sure you search properly before asking.
Since you have been forced to use the old and poorly designed GregorianCalendar class, the first thing you should do is convert each of the two GregorianCalendar objects to a modern type. Since Java 8 GregorianCalendar has a method that converts it to ZonedDateTime. Check the documentation, I include a link below.
Now that you’ve got two ZonedDateTime objects, there are different paths depending on your exact requirements. Often one will use Duration.between() for finding the duration, the amount of time between them in hours, minutes, seconds and fraction of second. If you know that you will always need just one of those time units, you may instead use for example ChronoUnit.HOURS.between() or ChronoUnit.MILLISECONDS.between(). If you need to count days, use ChronoUnit.DAYS.between().
If instead you need the time in months and days, you should instead use Period.between().
Links
Documentation:
GregorianCalendar (long outdated, don’t use unless forced to)
Duration
ChronoUnit
Period
Oracle tutorial: Date Time explaining how to use java.time, the modern Java date and time API to which ZonedDateTIme, Duration, ChronoUnit and Period belong.
In my project, I need to find duration of staying outside in office time of an employee from goToVisitTime and returnTime. The main concerning point is goToVisitTime and returnTime both are date (java.util) type [getting from other method, can't change anymore] and styingOutSideTime also must be date (java.util) type. For example:
Date goTOvisitTime = "12:25";
Date returnTime = "14:19";
So, output should be like,
styingOutSideTime = "01:54";
Therefore my method looks like below:
public Date getDiffTime(Date goTOvisitTime, Date returnTime) {
//calculate difference
return styingOutSideTime;
}
I have spent lots of time to determine the solution. I tried to use almost all of Date and Time from Java and Joda Time as well. Additionally, I went through the following links
How to calculate time difference in java?
Java how to calculate time differences
Convert seconds value to hours minutes seconds?
How to get hour/minute difference in java
However, almost all of the solutions are either parameter or return value is a string. additionally, returning either hour or minute only.
First of all, the duration should not be a Date, it should be a java.time.Duration.
If you only want to the hour part and the minute part, you can do it like this:
Duration duration = Duration.between(goTOvisitTime.toInstant(), returnTime.toInstant());
int hours = duration.toHoursPart();
int minutes = duration.toMinutesPart();
String formattedDuration = String.format("%02d:%02d", hours, minutes);
Given an epoch time: eg (1513213212) I should get 1 since its 1 am right now UTC. How would I go about converting it into the hour of the day? Is it possible to do it just using math (division, mod)?
It would be close to impossible to do it by using maths only. (Leap year and all). It's better to use established APIs which will do all the hard work.
You can use following method to do this.
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1513213212* 1000L);
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(cal.get(Calendar.HOUR));//12 hour clock
System.out.println(cal.get(Calendar.HOUR_OF_DAY));//24 hour clock
Use java.time, the modern Java date and time API also known as JSR-310:
LocalTime timeOfDay = Instant.ofEpochSecond(1513213212L)
.atOffset(ZoneOffset.UTC)
.toLocalTime();
System.out.println(timeOfDay);
int hourOfDay = timeOfDay.getHour();
System.out.println(hourOfDay);
This prints:
01:00:12
1
Even if you just wanted to do the math, I would still prefer to use standard library methods for it:
long epochSeconds = 1513213212L;
// convert the seconds to days and back to seconds to get the seconds in a whole number of days
long secondsInWholeDays = TimeUnit.DAYS.toSeconds(TimeUnit.SECONDS.toDays(epochSeconds));
long hourOfDay = TimeUnit.SECONDS.toHours(epochSeconds - secondsInWholeDays);
System.out.println(hourOfDay);
This too prints 1.
Your intention was “Given an epoch time: eg (1513213212) I should get 1 since it’s 1 AM right now UTC.” Which of the above code snippets in your opinion most clearly expresses this intention? This is what I would use for making my pick.
While MadProgrammer is surely correct in his/her comment that date and time arithmetic is complicated and that you should therefore leave it to the date and time API, I believe that this is one of the rare cases where not too complicated math gives the correct answer. It depends on it being safe to ignore the issue of leap seconds, and if going for the math solution, you should make sure to check this assumption. Personally I would not use it anyway.