Android : Compare two dates with different time zones [duplicate] - java

I have 2 date object in the database that represent the company's working hours.
I only need the hours but since I have to save date. it appears like this:
Date companyWorkStartHour;
Date companyWorkEndHour;
start hours: 12-12-2001-13:00:00
finish hours: 12-12-2001-18:00:00
I have the timezone of the company and of the user. (my server may be in another timezone).
TimeZone userTimeZone;
TimeZone companyTimeZone;
I need to check if the user's current time (considering his timezone) is within the company working hours (considering the company's time zone).
How can I do it? I am struggling for over a week with Java calendar and with no success!

The java.util.Date class is a container that holds a number of milliseconds since 1 January 1970, 00:00:00 UTC. Note that class Date doesn't know anyting about timezones. Use class Calendar if you need to work with timezones. (edit 19-Jan-2017: if you are using Java 8, use the new date and time API in package java.time).
Class Date is not really suited for holding an hour number (for example 13:00 or 18:00) without a date. It's simply not made for that purpose, so if you try to use it like that, as you seem to be doing, you'll run into a number of problems and your solution won't be elegant.
If you forget about using class Date to store the working hours and just use integers, this will be much simpler:
Date userDate = ...;
TimeZone userTimeZone = ...;
int companyWorkStartHour = 13;
int companyWorkEndHour = 18;
Calendar cal = Calendar.getInstance();
cal.setTime(userDate);
cal.setTimeZone(userTimeZone);
int hour = cal.get(Calendar.HOUR_OF_DAY);
boolean withinCompanyHours = (hour >= companyWorkStartHour && hour < companyWorkEndHour);
If you also want to take minutes (not just hours) into account, you could do something like this:
int companyWorkStart = 1300;
int companyWorkEnd = 1830;
int time = cal.get(Calendar.HOUR_OF_DAY) * 100 + cal.get(Calendar.MINUTE);
boolean withinCompanyHours = (time >= companyWorkStart && time < companyWorkEnd);

Try something like this:
Calendar companyWorkStart = new GregorianCalendar(companyTimeZone);
companyWorkStart.setTime(companyWorkStartHour);
Calendar companyWorkEnd = new GregorianCalendar(companyTimeZone);
companyWorkEnd.setTime(companyWorkEndHour);
Calendar user = new GregorianCalendar(userTimeZone);
user.setTime(userTime);
if(user.compareTo(companyWorkStart)>=0 && user.compareTo(companyWorkEnd)<=0) {
...
}

I haven't tried the Joda library. This code should work.
public boolean checkUserTimeZoneOverLaps(TimeZone companyTimeZone,
TimeZone userTimeZone, Date companyWorkStartHour,
Date companyWorkEndHour, Date userCurrentDate) {
Calendar userCurrentTime = Calendar.getInstance(userTimeZone);
userCurrentTime.setTime(userCurrentDate);
int year = userCurrentTime.get(Calendar.YEAR);
int month = userCurrentTime.get(Calendar.MONTH);
int day = userCurrentTime.get(Calendar.DAY_OF_MONTH);
Calendar startTime = Calendar.getInstance(companyTimeZone);
startTime.setTime(companyWorkStartHour);
startTime.set(Calendar.YEAR, year);
startTime.set(Calendar.MONTH, month);
startTime.set(Calendar.DAY_OF_MONTH, day);
Calendar endTime = Calendar.getInstance(companyTimeZone);
endTime.setTime(companyWorkEndHour);
endTime.set(Calendar.YEAR, year);
endTime.set(Calendar.MONTH, month);
endTime.set(Calendar.DAY_OF_MONTH, day);
if (userCurrentTime.after(startTime) && userCurrentTime.before(endTime)) {
return true;
}
return false;
}
EDIT
Updated the code to reflect Bruno's comments. Shouldn't be taking the dates of the company work timings.

Hey I am not sure how you would do this using the Java calendar but I would highly recommend using the Joda Time package. It's a much simpler system to use and it gives you direct methods to extracts all subcomponents of data and time and even just to create simple time objects without the date involved. Then I imagine it would be a matter of comparing the 2 timezone differences and subtracting the difference from the JodaTime object.

Related

How to get time Interval of date from Day , Hour and Minutes

I have variables which store the values
int day = Calender.SATURDAY;
int hour = 18;
int minutes = 33;
How can I convert this to Date? so
How I can find the time difference in milliseconds from Current date time?
Cases :
If the current date, time pass already passed,
for example: If the current day is Saturday, and now time is 19: 00, than get the next week date time interval.
If the current day is Saturday, and now time is 18: 30,
(the time interval should be 180000 milliseconds = 3 minutes).
How can I do this in android?
Please help me with finding the proper solution for this problem.
Create a Calendar (Calendar.getInstance()), set your fields (cal.set(Calendar.DAY, day), etc.) and then call getTime() on it - that will return a Date.
For a proper solution I strongly advise to use the modern functions provided by java.time instead of the deprecated java.util. Read this post and Convert java.util.Date to what “java.time” type? to understand the package. How to get java.time on android pre API 26 is described here: How to use ThreeTenABP in Android Project
If you have read those you can solve your problem along the lines of this example:
public void dateStuff() {
int day = DayOfWeek.SATURDAY.getValue();
int hour = 18;
int minutes = 33;
LocalDateTime now = LocalDateTime.now();
int dayDifference = now.getDayOfWeek().getValue() - day;
LocalDateTime date = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth() - dayDifference, hour, minutes);
long timeDifferenceNano = Duration.between(now, date).getNano();
long timeDifference = TimeUnit.NANOSECONDS.toMillis(timeDifferenceNano);
if (timeDifference > TimeUnit.MINUTES.toMillis(3)) {
//do stuff
}
}
Unfortunately I did not really understand when the two cases come into play, but I'm sure you can take it from here.

Subtract days from Current Date using Calendar Object

I am trying to subtract days from the current date using the java.util.Calendar object. My problem here is the days to subtract can be positive or negative. My code is as follows
public class Test {
public static void main(String[] args) {
int pastValidationDays=2;
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, - pastValidationDays);
}
}
As per the above code if the date is 20/1/2015 it will give me 18/1/2015
Now say if the pastValidationDays= -2(negative value) then also it should subtract from the current date. As per the above code if i say
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, - pastValidationDays);
then it is adding up the days instead of subtracting. Say if the current date 20/1/2015 it is giving me 22/1/2015. But in this case as well i need the date as 18/1/2015.
One of the way i am doing is as below
if (pastValidationDays < 0){
calendar.add(Calendar.DAY_OF_MONTH, pastValidationDays);
}else{
calendar.add(Calendar.DAY_OF_MONTH, -pastValidationDays);
}
Is this a good approach or can it be done this way
calendar.add(Calendar.DAY_OF_MONTH, - Math.abs(pastValidationDays));
I want to subtract the days using calendar object only. I do not want to use JODA time and other objects. Please suggest other approaches if any. Thanks in advance

adding/removing days from date code fix needed

I have this code here:
public static String AddRemoveDays(String date, int days) throws ParseException
{
SimpleDateFormat k = new SimpleDateFormat("yyyyMMdd");
Date d = k.parse(date);
d = new Date(d.getTime() + days*86400000);
String time = k.format(d);
return time;
}
It take String formed "yyyyMMdd", and adds int days to it. It should work then the days is negative - then he would substract the days from the date. When it does it's math, it returns String formated "yyyyMMdd".
At least that is what it should do. It works for small numbers, but if I try to add (or remove), for example, a year (365 or -365), it returns wierd dates.
What's the problem?
Should I do it a completley another way?
d = new Date(d.getTime() + days*86400000);
If you multiply 86400000 by 365 integer cant hold it. Change 86400000 to Long
d = new Date(d.getTime() + days*86400000L);
and it will be fine.
Hard to say what's going on without specific dates.
If you're committed to doing this with the raw Java classes, you might want to look at using Calendar -e.g.
Calendar calendar = Calendar.getInstance();
calendar.setTime(d);
calendar.add(Calendar.DATE, days); // this supports negative values for days;
d = calendar.getTime();
That said, I would recommend steering clear of the java Date classes, and look to use jodaTime or jsr310 instead.
e.g. in jsr310, you could use a DateTimeFormatter and LocalDate:
DateTimeFormatter format = DateTimeFormatters.pattern("yyyyMMdd");
LocalDate orig = format.parse(dateString, LocalDate.rule());
LocalDate inc = orig.plusDays(days); // again, days can be negative;
return format.print(inc);

JAVA - Is it a bug in java.util.Calendar class or what?

I have faced the same problem many times.
The Same Problem was With This Question and Got Solution Like the Same,
How to compare known hours ad current hour in android?
Problem :
When I use Calendar calCurr = Calendar.getInstance(); to get the Calendar object of current date and time, It always return me wrong.
I have put logs and checked it and to make it correct I had to add in years and months and then I got the correct object for Current Date and Time.
See My Example :
Calendar calCurr = Calendar.getInstance();
Log.i("Time in mili of Current - Normal", ""+calCurr.getTimeInMillis());
// see what it gives? dont know why?
Date date = new Date();
calCurr.set(date.getYear()+1900, date.getMonth()+1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
// so added one month to it
Log.i("Time in mili of Current - after update", ""+calCurr.getTimeInMillis());
// now get correct
Question :
Why it's giving the wrong output?
Is it a bug in there or My concept about the Calendar class is wrong?
tell me what should have been done
for that?
It works perfectly as expected if you change to getDate() it outputs :
Time in mili of Current - Normal Wed Apr 04 11:34:34 BST 2012
Time in mili of Current - after update Fri May 04 11:34:34 BST 2012
What do you expect ? And in milleseconds it also equals 30 days :
Time in mili of Current - Normal 1333535834557
Time in mili of Current - after update 1336127834557
and the calculation is (difference, divided by milliseconds in a day) :
1336127834557 - 1333535834557 = 2 592 000 000
2592000000 / 86400000 = 30
And todays date in milliseconds after 1970 is 1333536754 ... which fits, I don't see a problem.
EDIT
Your Problem is you are setting Month like 3 for march...there you need to set 2..cause months are indexed from 0 to 11.
Do not use date.getXXX(). Do not use any setter or getter except Date.getTime(). They are all deprecated. Using them would cause unexpected results.
If you call Calendar.getInstance(), it is already set to the current date. If you want to set or add days, months, whatever, set them on the calendar.
E.g. calCurr.set(Calendar.MONTH,2) or calCurr.add(Calendar.DAY,1).
It is NOT a bug, the Calendar is returning what it should (at least here it is).
Calendar calCurr = Calendar.getInstance();
Log.i("Time in mili of Current - Normal", ""+calCurr.getTimeInMillis());
// see what it gives? dont know why?
I got 1333546375707 milliseconds, which is the correct value (also calculated by hand).
Which value are you expecting here? How you know it is wrong?
Date date = new Date();
calCurr.set(date.getYear()+1900, date.getMonth()+1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
// so added one month to it
Why adding ONE to the month? Month of both Date and Calendar are zero-based - no need to add 1.
EDIT
Calculating by hand (approximated):
2012 - 42 years * 365.24 days/year * 86400 seconds/day
April - (31 + 29 + 31) days * 86400
4th - 3 days * 86400
13:30 - 13.5 hours * 3600 seconds/hour
====================
1333553112 seconds
Calendar months are zero-indexed. So when want to set for March its 2 not 3
Also, Don't set year, month and date from the Date object. If you must initialise a Calendar to a date, do it like this:
Calendar cal = Calendar.getInstance();
cal.setTime(date);
be aware that your Date object might be a different locale to what you think it is.
When Calendar object is created by using Calendar.getInstance() the instance variable "time" in the Calendar object is set and this value will get changed only if you use
Calendar.setTimeInMillis() function.
Code snippet from Calendar object:
public long getTimeInMillis() {
if (!isTimeSet) {
updateTime();
}
return time;
}
Here "isTimeSet" will become "true" when Calendar.getInstance() is called and it returns "time" every time without updating the time.
This is the reason you get the same value of time every time you call
calCurr.getTimeInMillis();
Hope this helps.
It's the weird implementation of Calendar.
For some reasons January is month 0, and years are not very logical as well.
I recommend Joda time library.
We are using below lines of code for finding current date and time It's working fine our side.
java.util.Calendar calc = java.util.Calendar.getInstance();
int day = calc.get(java.util.Calendar.DATE);
int month = calc.get(java.util.Calendar.MONTH)+1;
int year = calc.get(java.util.Calendar.YEAR);
String dayStr,monthStr;
if(day<10){
dayStr = "0"+day;
}else{
dayStr = ""+day;
}
if(month<10){
monthStr = "0"+month;
}else{
monthStr = ""+month;
}
/*String currentdate = monthStr+"/"+dayStr+"/"+year+" ";*/
String currentdate = dayStr+"/"+monthStr+"/"+year+" ";
/*String currenttime = currentdate + String.valueOf(calc.get(java.util.Calendar.HOUR_OF_DAY))+ ":"+
String.valueOf(calc.get(java.util.Calendar.MINUTE))+":"+String.valueOf(calc.get(java.util.Calendar.SECOND));*/
return currentdate;
Java Date Based API is not properly designed.
in future versions I think some problems of The API are planned to address.
I would recommend to use JodaTime.

Help with java calendar logic

I am working with the Java Calendar class to do the following:
Set a start date
Set an end date
Any date within that range is a "valid" date
I have this somewhat working, and somewhat not. Please see the code below:
nowCalendar.set(Calendar.DATE, nowCalendar.get(Calendar.DATE) + offset);
int nowDay = nowCalendar.get(Calendar.DATE);
Calendar futureCalendar = Calendar.getInstance();
futureCalendar.set(Calendar.DATE, nowDay + days);
Date now = nowCalendar.getTime();
Date endTime = futureCalendar.getTime();
long now_ms = now.getTime();
long endTime_ms = endTime.getTime();
for (; now_ms < endTime_ms; now_ms += MILLIS_IN_DAY) {
valid_days.addElement(new Date(now_ms));
System.out.println("VALID DAY: " + new Date(now_ms));
}
Basically, I set a "NOW" calendar and a "FUTURE" calendar, and then I compare the two calendars to find the valid days. On my calendar, valid days will be shaded white and invalid days will be shaded gray. You will notice two variables:
offset = three days after the current selected date
days = the number of valid days from the current selected date
This works...EXCEPT when the current selected date is the last day of the month, or two days prior (three all together). I think that its the offset that is definitely screwing it up, but the logic works everywhere else. Any ideas?
Don't fiddle with milliseconds. Clone the nowCalendar, add 1 day to it using Calendar#add() in a loop as long as it does not exceed futureCalendar and get the Date out of it using Calendar#getTime().
Calendar clone = nowCalendar.clone();
while (!clone.after(futureCalendar)) {
validDays.add(clone.getTime());
clone.add(Calendar.DATE, 1);
}
(note that I improved validDays to be a List instead of the legacy Vector)
Use add instead of set in the first line, otherwise the month is not adjusted if you are at the month boundary:
nowCalendar.add(Calendar.DATE, offset);
public boolean isInRange(Date d)
{
Calendar cal = Calendar.getInstance();
cal.setTime(d);
return cal.after(startCal) && cal.before(endCal);
}
Here the startCal is the calendar instance of start time and endCal is end time.
I found the problem:
As soon as I set futureCalendar to be a clone of nowCalendar (plus the additional days), then it started working. Thanks for everyone's suggestions!

Categories

Resources