Determining whether a length of time should be in minutes, hours, days - java

I have to show the time that has passed after a message has been posted. I'm writing a method the takes publisheddate as input and returns elapsed time.
d1.gettime-pubdate.gettime=time in milliseconds.
I'm writing an if-condition where
if time==something concat days ago,
elseif hours ago
elseif min ago
elseif seconds ago
elseif justnow.
What should the if-condition contain? E.g. days should be if(time>=1440) (if I take the date in minutes, which can be done by time/1000*60*60); what should I do for minutes, hours, &c.?
Based on the advice given here is what i wrote .any improvement suggestions??
public static String TimeElapsed(final Date date)
{
Date Interval=new Date();
DateTime Interval1 = new DateTime();//Converting java time to joda time
Interval1 = new DateTime(date);
DateTime Interval2 = new DateTime();
Interval2=new DateTime(Interval);
//Now we have two joda time instances
Duration dd=new Duration(Interval1,Interval2);
//get duration between given and current time
Duration rd1=new Duration(1000);//seconds
Duration rd2=new Duration(60000);//minutes
Duration rd7=new Duration(60000*2);//2minutes
Duration rd3=new Duration(3600000);//hours
Duration rd6=new Duration(3600000*2);//2hours
Duration rd4=new Duration(86400000);//days
Duration rd5=new Duration(86400000*2);//2days
if(dd.isShorterThan(rd1)){
String k="just now";
return k;
}
else if(dd.isEqual(rd1)){
String k="just now";
return k;
}
else if(dd.isLongerThan(rd1)&& dd.isShorterThan(rd2))
{
String k=dd.getStandardSeconds()+""+" seconds ago";
return k;
}
else if(dd.isEqual(rd2) || dd.isShorterThan(rd7)){
String k=dd.getStandardMinutes()+""+" minute ago";
return k;
}
else if(dd.isLongerThan(rd2) && dd.isShorterThan(rd3)){
String k=dd.getStandardMinutes()+""+" minutes ago";
return k;
}
else if(dd.isEqual(rd3) || dd.isShorterThan(rd6))
{
String k=dd.getStandardHours()+""+" hour ago";
return k;
}
else if(dd.isLongerThan(rd3) && dd.isShorterThan(rd4)){
String k=dd.getStandardHours()+""+"hours ago";
return k;
}
else if(dd.isEqual(rd4) || dd.isShorterThan(rd5) ) {
String k=dd.getStandardDays()+""+" day ago";
return k;
}
else if(dd.isLongerThan(rd4)){
String k=dd.getStandardDays()+""+" days ago";
return k;
}
else{
String k="";
return k;
}
}

I agree with wrschneider99's suggestion of using Joda-Time, but IMO you should be using a Duration rather than an Interval, assuming you're talking about an elapsed duration which is a fixed number of milliseconds, rather than something more human-centric such as a number of months.
I would suggest something like:
// Assuming this really is a constant...
private static final Duration POST_DURATION = Duration.standardDays(2);
// Then elsewhere...
Instant expiry = post.getTime().plus(POST_DURATION);
// See below
Instant now = clock.now();
if (now.isAfter(expiry)) {
...
}
Note that I'd use some sort of Clock interface with a "just for test" implementation and a "based on system time" implementation and inject that as you would any other dependency, for testability. See Kevin Bourrillion's blog post about pure functions for more on this.

I think you're looking for something like Joda Time's Period.normalizedStandard method.
See:
Period to string

Related

How can you check if a given time in milliseconds was yesterday?

Given a time in milliseconds, how can you check if it was yesterday?
You would first convert the millis to a Date or LocalDate and then run the comparison.
Here's a quick example:
import java.time.*;
class DateCheckSample {
public static void main(String[] args) {
// Our input date
long millis = System.currentTimeMillis();
// Convert the millis to a LocalDate
Instant instant = Instant.ofEpochMilli(millis);
LocalDate inputDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
// Grab today's date
LocalDate todaysDate = LocalDate.now();
System.out.println(millis);
// Check if date is yesterday
if (todaysDate.minusDays(1).equals(inputDate)) {
System.out.println(inputDate + " was yesterday!");
} else {
System.out.println(inputDate + " was NOT yeseterday!");
}
}
}
The Result:
2019-02-16 was NOT yesterday!
If you'd like to confirm it's working, just subtract 100000000 from millis before running.
Side Note: As pointed out in the comments on your question, 23:59 is not a millis value...
If you don't want to use Date, you can simply use the modulus operator with a bit of clever arithmetics. System#currentTimeMillis returns the amount of milliseconds that have passed since January 1, 1970, midnight (00:00).
Combining this with the number of milliseconds in a day (86,400,000), we can figure the time at which the last start of day was — which is when today began. Then we can see if the time given to us is smaller or larger than that value.
boolean isToday(long milliseconds) {
long now = System.currentTimeMillis();
long todayStart = now - (now % 86400000);
if(milliseconds >= todayStart) {
return true;
}
return false;
}
To check if a time is yesterday instead of today, we simply check if it is between the start of today and the start of yesterday.
boolean isYesterday(long milliseconds) {
long now = System.currentTimeMillis();
long todayStart = now - (now % 86400000);
long yesterdayStart = todayStart - 86400000;
if(milliseconds >= yesterdayStart && < todayStart) {
return true;
}
return false;
}
You can convert the milliseconds to Date and then compare the day with today's Date.
For reference: Convert millisecond String to Date in Java

Logic for call a function one time only in each 24 hour or in a day in java

i have one function
callEach24hourOneTime();
i have to call this function in each 24 hour only one time within 24 once it will executed then i don't have to call callEach24hourOneTime
i am unable to get current time hour minute and second in millis so that i can apply condition i tried below logic but unable to execute.
if(currentmillis=86400000 ){
callEach24hourOneTime();
}
else {
//dont call do other operation
}
please suggest me solution for this .
Logic to always have at least 24 hours between executions of the callEach24hourOneTime() method:
private long nextCallMillis;
long currentMillis = System.currentTimeMillis();
if (currentMillis >= this.nextCallMillis) {
this.nextCallMillis = currentMillis + 86400000/*24 hours*/;
callEach24hourOneTime();
} else {
// ...
}
That will cause a drift in time-of-day for the execution of the method. The speed of the drift is determined by how often the code is execute.
If you instead want method to be called at (around) the same time every day:
private long nextCallMillis;
long currentMillis = System.currentTimeMillis();
if (this.nextCallMillis == 0)
this.nextCallMillis = currentMillis; // Establish time-of-day
if (currentMillis >= this.nextCallMillis) {
this.nextCallMillis += ((currentMillis - this.nextCallMillis) / 86400000 + 1) * 86400000;
callEach24hourOneTime();
} else {
// ...
}
"Same time every day" is in UTC, so when crossing Daylight Savings Time changes, the time-of-day will change by 1 hour.
UPDATE
If you just want "once per day" logic:
private LocalDate lastCallDate;
LocalDate today = LocalDate.now();
if (! today.equals(lastCallDate)) {
this.lastCallDate = today;
callOnceDailyOneTime();
} else {
// ...
}
You can you a cron library.
I don't really know what language or framework you are currently using, but from spring I'd say you can use #Scheduled :
#Scheduled(cron = "0 0 0 * * *")
private void myMethod(){}
For exemple the cron above will make myMethod() execute once a day.

Check whether a given Instant fits a defined Period

What we get is an Instant and a "date-grid" defined by a period (which defines the interval of datapoints, e.g.: Every Month, Every 3 Months, etc.) and a start date where we started that grid.
private Instant getValidDate(Instant request, Instant start, Period period) {
if(isOnGrid(request, start, period)) {
return request;
}
else {
return getNextPriorDateOnGrid(request, start, period);
}
}
An example:
Given are the following parameters:
request = Instant("2000-05-02T07:42:00.000Z") //Second May of 2000 7:42 AM
start = Instant("2000-01-01T06:00:00.000Z") //First January of 2000 6:00 AM
period = Period("3M") //Every 3 Months
isOnGrid(request, start, period); //Should return false
getNextPriorDate(request, start, period) //Should return the First April of 2000 6:00 AM
I really have no idea how to get this with reasonable performance (its a critical place in code)
How do you check whether a distant future date (given by the Instant) is exactly on this grid, and if not, what is the next past date that was on the grid?
EDIT: I forgot to mention: All times and dates are assumed to be in UTC Timezone
Here is a simple test case that should match your requirements:
package test;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.ZoneId;
public class Java8PeriodAndInstant2 {
public static void main(String[] args) {
// LocalDate request=LocalDate.of(2000, 5, 2);
// LocalDate start=LocalDate.of(2000, 1, 1);
LocalDateTime start = Instant.parse("2000-01-01T06:00:00.000Z").atZone(ZoneId.of("UTC")).toLocalDateTime();
LocalDateTime request = Instant.parse("2000-05-02T07:42:00.000Z").atZone(ZoneId.of("UTC")).toLocalDateTime();
Period period = Period.ofMonths(3);
System.out.println("is on grid " + isOnGrid(request, start, period));
System.out.println("is on grid " + isOnGrid(LocalDateTime.of(2000, 4, 2,0,0), start, period));
System.out.println("is on grid " + isOnGrid(LocalDateTime.of(2000, 4, 1,0,0), start, period));
System.out.println("getNextPriorDate " + getNextPriorDate(request, start, period));
System.out.println("isOnGrid " + isOnGrid(Instant.parse("2000-01-03T05:00:00.000Z").atZone(ZoneId.of("UTC")).toLocalDateTime(), start, Period.ofDays(1)));
System.out.println("isOnGrid " + isOnGrid(Instant.parse("2000-01-03T06:00:00.000Z").atZone(ZoneId.of("UTC")).toLocalDateTime(), start, Period.ofDays(1)));
System.out.println("getNextPriorDate " + getNextPriorDate(Instant.parse("2000-01-03T05:00:00.000Z").atZone(ZoneId.of("UTC")).toLocalDateTime(), start, Period.ofDays(1)));
}
private static boolean isOnGrid(LocalDateTime start, LocalDateTime request, Period period) {
if (period.getDays() != 0) {
return ((Duration.between(start, request).toHours()%period.getDays())==0);
}
Period diffPeriod = Period.between(start.toLocalDate(), request.toLocalDate());
if (diffPeriod.getDays()!=0) {
return false;
}
if (period.getMonths() != 0) {
return ((diffPeriod.toTotalMonths()) % (period.toTotalMonths()) == 0);
}
if (diffPeriod.getMonths()!=0) {
return false;
}
if (period.getYears() != 0) {
return ((diffPeriod.getYears()) % (period.getYears()) == 0);
}
return false;
}
private static LocalDateTime getNextPriorDate(LocalDateTime request, LocalDateTime start, Period period) {
if (period.getDays() != 0) {
long hoursDiff=Duration.between(start, request).toHours();
return start.plusDays(hoursDiff/24);
}
Period diffPeriod = Period.between(start.toLocalDate(), request.toLocalDate());
if (period.getMonths() != 0) {
diffPeriod = diffPeriod.withDays(0);
long monthDiff = diffPeriod.toTotalMonths() % period.toTotalMonths();
return start.plus(diffPeriod).minusMonths(monthDiff);
}
if (period.getYears() != 0) {
diffPeriod = diffPeriod.withDays(0);
diffPeriod.withMonths(0);
long yearsDiff = diffPeriod.getYears() % period.getYears();
return start.plus(diffPeriod).minusYears(yearsDiff);
}
return null;
}
}
it works with periods of days or months or years.
You cannot add Periods to Instants. They have a different "scope".
An Instant i simply represents a point in the timeline, counting the amount of millis/nanos from a specific point in time called "Epoch".
At this instant i, the time at the clock at the wall (even the date in a calendar) differs around the world. It depends on the timezone you are in.
A Period respects different lengths of its representation among different timezones starting at differnt dates. For example: A month lasts 30 days in June but 31 days in August. And it is even more complex if daylight saving shifts occur.
An Instant has no idea, what a "month" actually is. You can parse it from a String and output it to it, but internally it does not represent a human understandable form of a month like 'Jan', 'Feb', ... .
This is, why you have to align an Instant to a LocalDateTime or ZonedDateTime using a ZoneId or an ZoneOffset. Theses classes understand and can work with Periods.
The following code converts your Instants to LocalDateTimes to take into account the above comments:
private static Instant getValidDate2(Instant request, Instant start, Period period)
{
assert(!request.isBefore(start));
// multiplication of period only works with days exclusive or
// zero daypart of period
assert(period.getDays() == 0 || (period.getMonths() == 0 && period.getYears() == 0));
ZoneId utcZone = ZoneOffset.UTC;
LocalDateTime ldstart = LocalDateTime.ofInstant(start, utcZone);
LocalDateTime ldreq = LocalDateTime.ofInstant(request, utcZone);
// calculate an approximation of how many periods have to be applied to get near request
Duration simpleDuration = Duration.between(ldstart, ldstart.plus(period));
Duration durationToReq = Duration.between(ldstart, ldreq);
int factor = (int) (durationToReq.toDays() / simpleDuration.toDays()); // rough approximation
// go near to request by a multiple of period
Period jump = Period.of(period.getYears() * factor, period.getMonths() * factor, period.getDays() * factor);
LocalDateTime ldRunning = ldstart.plus(jump);
// make sure ldRunning < request
while (ldRunning.isAfter(ldreq)) {
ldRunning = ldRunning.minus(period);
}
// make sure we pass request and
// save the the last date before or equal to request on the grid
LocalDateTime ldLastbefore = ldRunning;
while (!ldRunning.isAfter(ldreq)) {
ldLastbefore = ldRunning;
ldRunning = ldRunning.plus(period);
}
return ldLastbefore.equals(ldreq) ? request : ldLastbefore.atZone(utcZone).toInstant();
}
Explanation:
To avoid a loop adding period until it gets to request, a rough approximation is done on how often period must be added to start to come to request. A new period being a multiple of the request period is then added and aligned to get the last value of the grid which is less or equal to request. Depending on a comparation between the last value and request, the according instant is returned. In fact, the check is useless besides the fact, that request == request when it was on the grid and not only equal.
Here you can find further informations about java time: https://docs.oracle.com/javase/tutorial/datetime/overview/index.html

how to check : dateOne < dateTwo

I need help to check following conditions related to date and time...
Calendar cal = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
String CurrentDate= dateFormat.format(cal.getTime());
String ModifiedDate = dateTime taken from date n time picker widget ;
i have to check :
current ModifiedDate is not less than 5 minutes of current time
How to check this conditon in Android / Java..........?
Why are you formatting the date?
It's much easier to work with data in a "natural" representation rather than in a string representation. It's not clear whether your modified date has to be taken as a string, but if it does, the first thing you should do is parse it. You can then compare that with the current date and time using:
// Check if the value is later than "now"
if (date.getTime() > System.currentTimeMillis())
or
// Check if the value is later than "now + 5 minutes"
if (date.getTime() > System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5))
It's not really clear what you mean by "current ModifiedDate is not less than 5 minutes of current time" - whether you mean that it's not less than 5 minutes after, or not less than 5 minutes earlier, or something like that - but you should be able to change the code above to handle your requirements.
If you do a lot of date/time manipulation, I'd strongly recommend the use of Joda Time, which is a much better date/time API than java.util.Date/Calendar.
To check whether the given time is before/after the current time ,
There is a Calendar instance in Android...to compare date time values.
Calendar current_time = Calendar.getInstance ();
current_time.add(Calendar.DAY_OF_YEAR, 0);
current_time.set(Calendar.HOUR_OF_DAY, hrs);
current_time.set(Calendar.MINUTE, mins );
current_time.set(Calendar.SECOND, 0);
Calendar given_time = Calendar.getInstance ();
given_time.add(Calendar.DAY_OF_YEAR, 0);
given_time.set(Calendar.HOUR_OF_DAY, hrs);
given_time.set(Calendar.MINUTE, mins );
given_time.set(Calendar.SECOND, 0);
current_time.getTime();
given_time.getTime();
boolean v = current_calendar.after(given_calendar);
// it will return true if current time is after given time
if(v){
return true;
}
public static boolean getTimeDiff(Date dateOne, Date dateTwo) {
long timeDiff = Math.abs(dateOne.getTime() - dateTwo.getTime());
int day = (int) TimeUnit.MILLISECONDS.toHours(timeDiff);
int min= (int) ( TimeUnit.MILLISECONDS.toMinutes(timeDiff) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeDiff)));
if(day>1)
{
return false;
}
else if(min>5)
{
return false;
}
else
{
return true;
}
}
usage:
System.out.println(getTimeDiff(new Date("01/13/2012 12:05:00"),new Date("01/12/2012 13:00:00")));

Elapsed time without considering weekends and bank holidays in Java

I've implemented a stopwatch that works fine without considering that bank holidays and weekends shouldn't be counted in the total duration. I was looking for some open-source library where I could get the elapsed time, passing a start instant, end instant and a set of bank holidays (weekends aren't counted in). The only library that makes me things easier is net.sf.jtemporal, but I have still to amplify the functionality.
Could anyone tell me if there is some useful library to get the wanted functionality?
As I have mentioned there, probably the best and easiest approach is to create a table containing information about each day (work day count from beginning / bank holiday, etc; one row per day = 365 rows per year) and then just use count function / with proper selection.
I doubt you can find something that specific. But it's easy enough to create your own logic. Here's some pseudocode...
private long CalculateTimeSpan(DateTime BeginDate, DateTime EndDate, ArrayList<DateTime> BankHollidays)
{
long ticks = 0;
while (BeginDate <= EndDate) // iterate until reaching end
{
if ((BeginDate is holliday?) || (BeginDate is Weekend?))
skip;
else
ticks += (24*60*60*1000);
BeginDate = BeginDate + 1 day; // add one day and iterate
}
return ticks;
}
Do you only count Bank Hours too? 9AM - 3PM? Or is it 24 hours a day?
You should take a look at Joda Time. It is a much better date/time API than the one included with Java
I think this would be a valid solution to what your are looking for. It calculates the elapsed time (considering that one working day has 24 hours) without count the bank holidays and weekends in:
/**
* Calculate elapsed time in milliseconds
*
* #param startTime
* #param endTime
* #return elapsed time in milliseconds
*/
protected long calculateElapsedTimeAux(long startTime, long endTime) {
CustomizedGregorianCalendar calStartTime = new CustomizedGregorianCalendar(this.getTimeZone());
CustomizedGregorianCalendar calEndTime = new CustomizedGregorianCalendar(this.getTimeZone());
calStartTime.setTimeInMillis(startTime);
calEndTime.setTimeInMillis(endTime);
long ticks = 0;
while (calStartTime.before(calEndTime)) { // iterate until reaching end
ticks = ticks + increaseElapsedTime(calStartTime, calEndTime);
}
return ticks;
}
private long increaseElapsedTime(CustomizedGregorianCalendar calStartTime, CustomizedGregorianCalendar calEndTime) {
long interval;
long ticks = 0;
interval = HOURS_PER_DAY*MINUTES_PER_HOUR*SECONDS_PER_MIN*MILLISECONDS_PER_SEC; // Interval of one day
if ( calEndTime.getTimeInMillis() - calStartTime.getTimeInMillis() < interval) {
interval = calEndTime.getTimeInMillis() - calStartTime.getTimeInMillis();
}
ticks = increaseElapsedTimeAux(calStartTime, calEndTime, interval);
calStartTime.setTimeInMillis(calStartTime.getTimeInMillis() + interval);
return ticks;
}
protected long increaseElapsedTimeAux(CustomizedGregorianCalendar calStartTime, CustomizedGregorianCalendar calEndTime, long interval) {
long ticks = 0;
CustomizedGregorianCalendar calNextStartTime = new CustomizedGregorianCalendar(this.getTimeZone());
calNextStartTime.setTimeInMillis(calStartTime.getTimeInMillis() + interval);
if ( (calStartTime.isWorkingDay(_nonWorkingDays) && calNextStartTime.isWorkingDay(_nonWorkingDays)) ) { // calStartTime and calNextStartTime are working days
ticks = interval;
}
else {
if (calStartTime.isWorkingDay(_nonWorkingDays)) { // calStartTime is a working day and calNextStartTime is a non-working day
ticks = (calStartTime.getNextDay().getTimeInMillis() - calStartTime.getTimeInMillis());
}
else {
if (calNextStartTime.isWorkingDay(_nonWorkingDays)) { // calStartTime is a non-working day and calNextStartTime is a working day
ticks = (calNextStartTime.getTimeInMillis() - calStartTime.getNextDay().getTimeInMillis());
}
else {} // calStartTime and calEndTime are non-working days
}
}
return ticks;
}

Categories