Parsing Time difference - java

I am getting confused while parsing a time difference[which I receive from a webpage].
For Example : I get a string like this : 2 years 10 weeks 3 days 6 hours 7 min ago. Please note that the trailing s in year, week, day and hour may not be there in case of unity and not present in the min.
Currently, I want to get the difference stored like that and get the actual date and time[by subtracting from the current time?].
And, I am confused what to do? I know about the Time parsing methods but its not a regular time, Plus there's that trailing s!!!
Can anyone suggest a good approach to this?

I'd recomend calculating how much time the difference is in milliseconds then subtracting that from now, that would be simple however you will run into an issue with leap years.
Calendar cal = Calendar.getInstance();
cal.add(Calendar.YEAR, -2);
cal.add(Calendar.WEEK_OF_YEAR, -10);
cal.add(Calendar.DAY_OF_YEAR, -3);
cal.add(Calendar.HOUR_OF_DAY, -6);
cal.add(Calendar.MINUTE, -7);
that should work fine, but I haven't tested it. you're also going to have to handle cases where you don't get a value for weeks for example.

You can use this code. This takes in accoutn the ss and the possible absense of some tokens.
String orig = "2 years 10 weeks 3 days 6 hours 7 min ago";
String[] split = orig.replaceAll("[^0-9]+", " ").trim().split(" ");
Calendar cal = Calendar.getInstance();
int idx = 0;
if (orig.contains("yea")) cal.add(Calendar.YEAR, -Integer.parseInt(split[idx++]));
if (orig.contains("wee")) cal.add(Calendar.WEEK_OF_MONTH, -Integer.parseInt(split[idx++]));
if (orig.contains("day")) cal.add(Calendar.DATE, -Integer.parseInt(split[idx++]));
if (orig.contains("hour")) cal.add(Calendar.HOUR, -Integer.parseInt(split[idx++]));
if (orig.contains("min")) cal.add(Calendar.MINUTE, -Integer.parseInt(split[idx++]));
SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
String formattedString = sdf.format(cal.getTime());
System.out.println(formattedString); // it prints 04-26-2011 02:12:54

Using #Eluvatar's suggestion, assumg a space between each part:
Calendar cal = Calendar.getInstance();
String original = "2 years 10 weeks 3 days 6 hours 7 min ago";
// Split on whitespace separators ("\s+" means "one or more whitespace characters"),
// having trimmed whitespace at beginning and end.
String[] split = original.trim().split("\s+");
// Now parse each entry
int num = split.length;
int pos = 0;
while ((num-pos) >= 2) {
if (split[pos].regionMatches(true, 0, "year", 0, 4)) {
cal.add(Calendar.YEAR, -Integer.decode(split[++pos]));
}
else if (split[pos].regionMatches(true, 0, "month", 0, 5)) {
cal.add(Calendar.MONTH, -Integer.decode(split[++pos]));
}
else if (split[pos].regionMatches(true, 0, "week", 0, 4)) {
cal.add(Calendar.WEEK_OF_YEAR, -Integer.decode(split[++pos]));
}
// And so on through the other potential values, note that the last
// number in regionMatches is the number of characters to match.
pos++;
}
The "\s+" may need to become "\s+", see How do I split a string with any whitespace chars as delimiters?.

Related

Calendar specified week keeps resetting

I have a function to return all dates for a specific week.
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM");
Calendar cal = Calendar.getInstance();
cal.set(Calendar.WEEK_OF_YEAR, week);
String[] dates = new String[7];
currentlySelectedYear = String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
// i = 2 because MONDAY is day two in week
for (int i = 2; i < 9; i++) {
cal.set(Calendar.DAY_OF_WEEK, i);
//i-2 to start the array at index 0
dates[i - 2] = sdf.format(cal.getTime());
}
it works fine on all devices except samsung where each time the for loop is entered again after the first iteration the WEEK_OF_YEAR field in the calendar is reset to current week instead of the week set three lines above.
Is this a known bug for samsung or am I missing something?
Is there another way to do the same thing that maybe work on all devices?

Getting incorrect results when calculating difference between two times

I am working on an android app to keep track of hours between signing in and out.
An employee can sign in one day and sign out the next day or within the same day.
Within the app, I have a function that should calculate the difference between two times.
But I am not getting the correct results...
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("h:mma");
Date start;
Date end;
double difference;
//Test 1
start = simpleDateFormat.parse("7:00AM");
end = simpleDateFormat.parse("3:30PM");
difference = end.getTime() - start.getTime();
Log.d("difference", String.valueOf(difference)); // 3.06E7
Log.d("Time difference", String.valueOf(((difference/1000)/60)/60));
//Prints '8.5' correct.
// Text 2
start = simpleDateFormat.parse("11:00PM");
end = simpleDateFormat.parse("7:30AM");
difference = end.getTime() - start.getTime();
Log.d("difference2", String.valueOf(difference)); // -5.58E7
Log.d("Time difference2", String.valueOf(((difference/1000)/60)/60));
//Prints '-15.5' but should print '8.5'
As you can see... the first test works correctly, yet the second test fails.
How can I resolve this issue?
Your current issue is that your are calculating the difference between two hours and these hours are technically on the same day.
You are currently calculating the time difference between (A) Day 1: 23:00 and (b) Day 1: 7:30. 7:30 is 15.5 hours before 23:00.
You will need to add your starting and ending dates.
Exemple:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date day1 = simpleDateFormat.parse("12/10/2017 23:00:00");
Date day2 = simpleDateFormat.parse("13/10/2017 07:30:00");
DateTime dt1 = new DateTime(day1);
DateTime dt2 = new DateTime(day2);
System.out.print(Hours.hoursBetween(dt1, dt2).getHours() % 24 + " hours, ");
System.out.print(Minutes.minutesBetween(dt1, dt2).getMinutes() % 60 + " minutes.");
// Should print "8 hours, 30 minutes.'
start is after end (on same day), hence a negative result; -15.5 + 24 == 8.5. A modulo 24 is in order:
difference = end.getTime() - start.getTime();
difference = difference/1000/60/60;
if (difference < 0) {
difference += 24;
}
Log.d("Time difference", String.valueOf(difference));

how to increase date concerning a working week? [duplicate]

This question already has answers here:
How do I ignore weekends using the Java calendar?
(2 answers)
Closed 7 years ago.
I have a date in java, and I would like to add a certain amount of working time to it.
However, it should consider a working week.
8 Hours days (8:00 to 16:00),
and
no work on weekends (Saturday/Sunday).
So I have a Date object giving the current time. I also have a double, which are the minutes to be added to that date. What would be the best way of doing this?
I'm using Java 8.
Some examples:
Working on the same day:
Date date = new Date(2000, 1, 1, 8, 0); //so first of jan, 8:00. Let's assume this is a monday.
double minutes = 4 * 60;
Date newDate = addWorkingTime(date, minutes);
// newDate should be the same day, 12:00
Working over multiple days:
Date date = new Date(2000, 1, 1, 14, 0); //so first of jan, 14:00. Let's assume this is a monday.
double minutes = 4 * 60;
Date newDate = addWorkingTime(date, minutes);
// newDate should be the next day, 10:00
// 2 hours on the first day, the next two hours of work on the next.
Working over a weekend:
Date date = new Date(2000, 1, 5, 14, 0); //so fifth of jan, 14:00. Let's assume this is a friday.
double minutes = 8 * 60;
Date newDate = addWorkingTime(date, minutes);
// newDate should be the next monday, 14:00
// 2 hours on the first day, the next six hours of work the next monday.
Thanks!
You can use this method:
public static LocalDateTime addWorkingMinutes(LocalDateTime date, long minutes) {
if (date.getHour() < 8) {
// Working day hasn't started. Reset date to start of this working day
date = date.withHour(8).withMinute(0).withSecond(0);
}
// Take care of weekends
if (date.getDayOfWeek() == DayOfWeek.SATURDAY) {
date = date.plusDays(2);
} else if (date.getDayOfWeek() == DayOfWeek.SUNDAY) {
date = date.plusDays(1);
}
LocalDateTime endOfCurrentWorkingDay = date.withHour(16).withMinute(0).withSecond(0);
// Get minutes from date to endOfCurrentWorkingDay
long minutesCovered = ChronoUnit.MINUTES.between(date, endOfCurrentWorkingDay);
if (minutesCovered > minutes) {
// If minutesCovered covers the minutes value passed, that means result is the same working
// day. Just add minutes and return
return date.plusMinutes(minutes);
} else {
// Calculate remainingMinutes, and then recursively call this method with next working day
long remainingMinutes = minutes - minutesCovered;
return addWorkingMinutes(endOfCurrentWorkingDay.plusDays(1).withHour(8), remainingMinutes);
}
}
tested with your sample input, and some other inputs on my end, considering weekends.
Note: I'm using Java 8 DateTime API, since you're already on Java 8, there shouldn't be any excuse to still use Date.

Error count days between two days in Java [duplicate]

This question already has answers here:
Calculating the difference between two Java date instances
(45 answers)
Closed 8 years ago.
Possible Duplicate:
Calculating the Difference Between Two Java Date Instances
In Java, I want to calculate the number of days between two dates.
In my database they are stored as a DATE datatype, but in my code they are strings.
I want to calculate the no of days between those two strings.
Note: this answer was written in 2011. I would recommend using java.time now instead of Joda Time.
Well to start with, you should only deal with them as strings when you have to. Most of the time you should work with them in a data type which actually describes the data you're working with.
I would recommend that you use Joda Time, which is a much better API than Date/Calendar. It sounds like you should use the LocalDate type in this case. You can then use:
int days = Days.daysBetween(date1, date2).getDays();
Java 8 and later: ChronoUnit.between
Use instances of ChronoUnit to calculate amount of time in different units (days,months, seconds).
For Example:
ChronoUnit.DAYS.between(startDate,endDate)
try this code
Calendar cal1 = new GregorianCalendar();
Calendar cal2 = new GregorianCalendar();
SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");
Date date = sdf.parse("your first date");
cal1.setTime(date)
date = sdf.parse("your second date");
cal2.setTime(date);
//cal1.set(2008, 8, 1);
//cal2.set(2008, 9, 31);
System.out.println("Days= "+daysBetween(cal1.getTime(),cal2.getTime()));
this function
public int daysBetween(Date d1, Date d2){
return (int)( (d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24));
}
I know this thread is two years old now, I still don't see a correct answer here.
Unless you want to use Joda or have Java 8 and if you need to subract dates influenced by daylight saving.
So I have written my own solution. The important aspect is that it only works if you really only care about dates because it's necessary to discard the time information, so if you want something like 25.06.2014 - 01.01.2010 = 1636, this should work regardless of the DST:
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy");
public static long getDayCount(String start, String end) {
long diff = -1;
try {
Date dateStart = simpleDateFormat.parse(start);
Date dateEnd = simpleDateFormat.parse(end);
//time is always 00:00:00, so rounding should help to ignore the missing hour when going from winter to summer time, as well as the extra hour in the other direction
diff = Math.round((dateEnd.getTime() - dateStart.getTime()) / (double) 86400000);
} catch (Exception e) {
//handle the exception according to your own situation
}
return diff;
}
As the time is always 00:00:00, using double and then Math.round() should help to ignore the missing 3600000 ms (1 hour) when going from winter to summer time, as well as the extra hour if going from summer to winter.
This is a small JUnit4 test I use to prove it:
#Test
public void testGetDayCount() {
String startDateStr = "01.01.2010";
GregorianCalendar gc = new GregorianCalendar(locale);
try {
gc.setTime(simpleDateFormat.parse(startDateStr));
} catch (Exception e) {
}
for (long i = 0; i < 10000; i++) {
String dateStr = simpleDateFormat.format(gc.getTime());
long dayCount = getDayCount(startDateStr, dateStr);
assertEquals("dayCount must be equal to the loop index i: ", i, dayCount);
gc.add(GregorianCalendar.DAY_OF_YEAR, 1);
}
}
... or if you want to see what it does 'life', replace the assertion with just:
System.out.println("i: " + i + " | " + dayCount + " - getDayCount(" + startDateStr + ", " + dateStr + ")");
... and this is what the output should look like:
i: 0 | 0 - getDayCount(01.01.2010, 01.01.2010)
i: 1 | 1 - getDayCount(01.01.2010, 02.01.2010)
i: 2 | 2 - getDayCount(01.01.2010, 03.01.2010)
i: 3 | 3 - getDayCount(01.01.2010, 04.01.2010)
...
i: 1636 | 1636 - getDayCount(01.01.2010, 25.06.2014)
...
i: 9997 | 9997 - getDayCount(01.01.2010, 16.05.2037)
i: 9998 | 9998 - getDayCount(01.01.2010, 17.05.2037)
i: 9999 | 9999 - getDayCount(01.01.2010, 18.05.2037)
here's a small program which may help you:
import java.util.*;
public class DateDifference {
public static void main(String args[]){
DateDifference difference = new DateDifference();
}
DateDifference() {
Calendar cal1 = new GregorianCalendar();
Calendar cal2 = new GregorianCalendar();
cal1.set(2010, 12, 1);
cal2.set(2011, 9, 31);
System.out.println("Days= "+daysBetween(cal1.getTime(),cal2.getTime()));
}
public int daysBetween(Date d1, Date d2) {
return (int)( (d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24));
}
}
// http://en.wikipedia.org/wiki/Julian_day
public static int julianDay(int year, int month, int day) {
int a = (14 - month) / 12;
int y = year + 4800 - a;
int m = month + 12 * a - 3;
int jdn = day + (153 * m + 2)/5 + 365*y + y/4 - y/100 + y/400 - 32045;
return jdn;
}
public static int diff(int y1, int m1, int d1, int y2, int m2, int d2) {
return julianDay(y1, m1, d1) - julianDay(y2, m2, d2);
}
I'm really really REALLY new at Java, so i'm sure that there's an even better way to do what i'm proposing.
I had this same demand and i did it using the difference between the DAYOFYEAR of the two dates.
It seemed an easier way to do it...
I can't really evaluate this solution in performance and stability terms, but i think it's ok.
here:
public static void main(String[] args) throws ParseException {
//Made this part of the code just to create the variables i'll use.
//I'm in Brazil and the date format here is DD/MM/YYYY, but wont be an issue to you guys.
//It will work anyway with your format.
String s1 = "18/09/2014";
String s2 = "01/01/2014";
DateFormat f = DateFormat.getDateInstance();
Date date1 = f.parse(s1);
Date date2 = f.parse(s2);
//Here's the part where we get the days between two dates.
Calendar day1 = Calendar.getInstance();
Calendar day2 = Calendar.getInstance();
day1.setTime(date1);
day2.setTime(date2);
int daysBetween = day1.get(Calendar.DAY_OF_YEAR) - day2.get(Calendar.DAY_OF_YEAR);
//Some code just to show the result...
f = DateFormat.getDateInstance(DateFormat.MEDIUM);
System.out.println("There's " + daysBetween + " days between " + f.format(day1.getTime()) + " and " + f.format(day2.getTime()) + ".");
}
In this case, the output would be (remembering that i'm using the Date Format DD/MM/YYYY):
There's 260 days between 18/09/2014 and 01/01/2014.
This function is good for me:
public static int getDaysCount(Date begin, Date end) {
Calendar start = org.apache.commons.lang.time.DateUtils.toCalendar(begin);
start.set(Calendar.MILLISECOND, 0);
start.set(Calendar.SECOND, 0);
start.set(Calendar.MINUTE, 0);
start.set(Calendar.HOUR_OF_DAY, 0);
Calendar finish = org.apache.commons.lang.time.DateUtils.toCalendar(end);
finish.set(Calendar.MILLISECOND, 999);
finish.set(Calendar.SECOND, 59);
finish.set(Calendar.MINUTE, 59);
finish.set(Calendar.HOUR_OF_DAY, 23);
long delta = finish.getTimeInMillis() - start.getTimeInMillis();
return (int) Math.ceil(delta / (1000.0 * 60 * 60 * 24));
}
My best solution (so far) for calculating the number of days difference:
// This assumes that you already have two Date objects: startDate, endDate
// Also, that you want to ignore any time portions
Calendar startCale=new GregorianCalendar();
Calendar endCal=new GregorianCalendar();
startCal.setTime(startDate);
endCal.setTime(endDate);
endCal.add(Calendar.YEAR,-startCal.get(Calendar.YEAR));
endCal.add(Calendar.MONTH,-startCal.get(Calendar.MONTH));
endCal.add(Calendar.DATE,-startCal.get(Calendar.DATE));
int daysDifference=endCal.get(Calendar.DAY_OF_YEAR);
Note, however, that this assumes less than a year's difference!
If you're sick of messing with java you can just send it to db2 as part of your query:
select date1, date2, days(date1) - days(date2) from table
will return date1, date2 and the difference in days between the two.

Unable to find difference between two dates w.r.t time,seconds,months and years?

This is my java class
public class dateparse {
public static void main(String args[]) throws ParseException
{
Date dd=new Date();
int year = Calendar.getInstance().get(Calendar.YEAR);
int month=0;
int calc_days=0;
String d1 = dd.getDate()+"/"+dd.getMonth()+"/"+year;
String d2 = "19/1/2014";
SimpleDateFormat s1 = new SimpleDateFormat("dd/mm/yyyy");
SimpleDateFormat s2 = new SimpleDateFormat("dd/mm/yyyy");
Date dateOne = new SimpleDateFormat("dd/mm/yyyy").parse(d1);
Date dateTwo = s2.parse(d2);
long diff = dateOne.getTime() - dateTwo.getTime();
calc_days= (int) (diff / 1000 / 60 / 60 / 24 / 1);
}
}
I am trying to find the difference between current date and the date specified with respect to seconds,minutes,hours,days,months and years.Here my input date is 19th Feb 2014.I want to show the difference in no of days(e.g. 10 days) or months+days(e.g.1 month and 2 days) or year+month+days(e.g. 1 year and 2 months and 4 days).But when I run this code it returns difference as -10 days.
Your error is your parsing. Lowercase m means minutes, not month:
SimpleDateFormat s2 = new SimpleDateFormat("dd/mm/yyyy");
should be:
SimpleDateFormat s2 = new SimpleDateFormat("dd/MM/yyyy");
Here's a simplified example:
String d1 = "21/1/2014";
String d2 = "19/1/2014";
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date dateOne = sdf.parse(d1);
Date dateTwo = sdf.parse(d2);
long diff = dateOne.getTime() - dateTwo.getTime();
int differenceInDays = (int) (diff / 1000 / 60 / 60 / 24 / 1);
System.out.println(differenceInDays);
Prints: 2
This is a classic error caused by the horrible API that Java has provided:
date.getMonth() returns 0 for January, 1 for february... and 11 for December. If you can, try to avoid java.util.Date and Calendar :P
Attention - Accepted answer is wrong! Prove:
Use as input the dates 2014-03-19 and 2014-04-01 in my timezone "Europe/Berlin". The true answer is 13 days as everyone can easily veryify using standard calendars, but the accepted code of #Duncan produces 12 days because in my timezone there was a dst-jump which breaks the basis of calculation formular (1 day = 24 hours). On 30th of March the day was only 23 hours long.
The JDK pre 8 does not offer a built-in generic solution for this problem. Please also note that your input is just a pair of two plain dates with no time. Therefore it is silly to ask for the difference in seconds, etc. Only asking for the difference in days, months, weeks or years is sensible. In Java 8 you can do following:
// only days
LocalDate start = LocalDate.of(2014, 3, 19); // start in March
LocalDate end = LocalDate.of(2014, 4, 1);
int days = ChronoUnit.DAYS.between(start, end); // 13
// period in years, months and days
LocalDate start = LocalDate.of(2014, 2, 19); // start in February
LocalDate end = LocalDate.of(2014, 4, 1);
Period period = Period.between(start, end); // P1M13D = 1 month + 13 days
Unfortunately you are not free to choose in which calendar units you like to get the difference expressed. JodaTime (and my library) has a more flexible approach using PeriodType.

Categories

Resources