When starting from ajava.util.date object: what is the best way getting the hour part as an integer regarding performance?
I have to iterate a few million dates, thus performance matters.
Normally I'd get the hour as follows, but maybe there are better ways?
java.util.Date date;
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int hours = calendar.get(Calendar.HOUR_OF_DAY);
In UTC:
int hour = (int)(date.getTime() % 86400000) / 3600000;
or
long hour = (date.getTime() % 86400000) / 3600000;
Date dateInput = new Date();
since calendar starts at 01.01.1970, 01:00. you have to make further modifications
to the code.using below approach avoids that so this will performs faster.
dateInput.toInstant().atZone(ZoneId.systemDefault()).getHour();
Related
In my application, I have setup 2 TimePickers inside my activity. This is currently how I get the values from the 2 TimePickers:
int hour1 = mFirstWakeUpTimePicker.getCurrentHour();
int min1 = mFirstWakeUpTimePicker.getCurrentMinute();
int hour2 = mSecondWakeUpTimePicker.getCurrentHour();
int min2 = mSecondWakeUpTimePicker.getCurrentMinute();
GregorianCalendar calendar1 = new GregorianCalendar();
GregorianCalendar calendar2 = new GregorianCalendar();
calendar1.set(Calendar.HOUR_OF_DAY, hour1);
calendar1.set(Calendar.MINUTE, min1);
calendar2.set(Calendar.HOUR_OF_DAY, hour2);
calendar2.set(Calendar.MINUTE, min2);
After that, I need to compare them to check if they are at least 3 minutes apart. How do I achieve this? Also, what's the better way of writing this code?
Any help is appreciated.
Assuming you want calendar2 to be late then three mins with respect to calendar1 you can do like this, right after getting hours and mins from Timepickers:
GregorianCalendar calendar1 = new GregorianCalendar();
GregorianCalendar calendar2 = new GregorianCalendar();
calendar1.set(Calendar.HOUR_OF_DAY, hour1);
calendar1.set(Calendar.MINUTE, min1);
calendar2.set(Calendar.HOUR_OF_DAY, hour2);
calendar2.set(Calendar.MINUTE, min2);
long millisCal1 = calendar1.getTimeInMillis();
long millisCal2 = calendar2.getTimeInMillis();
if (millisCal2 - millisCal1 >= 1000 * 60 * 3){
// They differ of at least three mins
} else {
// They not differ of at least three mins
}
Where three mins is translated in millis 1000 * 60 * 3.
If you want to check calendar1 later than calendar2 just switch the order inside the if statement.
Bye
you could compare calendar1 with calendar2 by using method "calendar.getTimeInMillis()",as following:
int minutes = (int) ((calendar2.getTimeInMillis()-calendar1.getTimeInMillis())/(1000 * 60)) ;
If you have two date you can check these by the following conditions:
if(calendar1.isBefore(calendar2)){
// conditions here
}
and you can also check the same for isAfter
OR
if you want to check for atleast 3 minutes add the dates and then comapre them like:
Calendar calendar = Calendar.getInstance();
calendar.setTime(dat1);
calendar.add(Calendar.MINUTE, dat2);
Try this and let me know if it helps.
I have Integer fields:
currentYear,currentMonth,currentDay,currentHour,currentMinute and nextYear,nextMonth,nextDay,nextHour,nextMinute.
How I can get difference between those two spots in time in milliseconds.
I found a way using Date() object, but those functions seems to be depricated, so it's little risky.
Any other way?
Use GregorianCalendar to create the date, and take the diff as you otherwise would.
GregorianCalendar currentDay=new GregorianCalendar (currentYear,currentMonth,currentDay,currentHour,currentMinute,0);
GregorianCalendar nextDay=new GregorianCalendar (nextYear,nextMonth,nextDay,nextHour,nextMinute,0);
diff_in_ms=nextDay. getTimeInMillis()-currentDay. getTimeInMillis();
Create a Calendar object for currenDay and nextDay, turn them into longs, then subtract. For example:
Calendar currentDate = Calendar.getInstance();
Calendar.set(Calendar.MONTH, currentMonth - 1); // January is 0, Feb is 1, etc.
Calendar.set(Calendar.DATE, currentDay);
// set the year, hour, minute, second, and millisecond
long currentDateInMillis = currentDate.getTimeInMillis();
Calendar nextDate = Calendar.getInstance();
// set the month, date, year, hour, minute, second, and millisecond
long nextDateInMillis = nextDate.getTimeInMillis();
return nextDateInMillis - currentDateInMillis; // this is what you want
If you don't like the confusion around the Calendar class, you can check out the Joda time library.
Calculating the difference between two dates (java.util.Date) in terms of no. of days look like very simple and we can find different ways to do that. I used the following code to calculate the date difference:
public static long daysBetween(Calendar startDate, Calendar endDate) {
Calendar date = (Calendar) startDate.clone();
long daysBetween = 0;
while (date.before(endDate)) {
date.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
return daysBetween;
}
In main(), I used the following two dates :
Calendar c1 = Calendar.getInstance();
c1.set(2011, 1, 1);
Calendar c2 = Calendar.getInstance();
c2.set(2011, 1, 31);
long difference = daysBetween(c1, c2); //
But the value of the variable difference is not consistent. It is sometimes 30 and sometimes 31. So, why that might have happened.
Is there any solution to use the method results a consistent output ?
You're setting the date part of the calendars, but not the time part.
Sometimes the clock will tick between the calls to getInstance() and sometimes it won't, hence the inconsistency.
Options:
Set the time as well as the date, e.g. to midnight
Use a better date/time library - Joda Time - which has a more suitable representation (LocalDate). An important moral here is that if you can find a type which represents the exact information you have, and nothing else, that's likely to be a good fit and cause fewer complications.
Using LocalDate, you wouldn't even have to do the loop as Joda Time has good support for computing the differences between two values anyway.
LocalDate date1 = new LocalDate(2011, 1, 1);
LocalDate date2 = new LocalDate(2011, 1, 31);
Days period = Days.daysBetween(days1, days2);
int days = period.getDays();
You are only setting the year, month and day. The hours, minutes, seconds and milli-seconds are the current time (and thus different every time you run it)
I suggest you use Joda Time's LocalDate instead as it appears to does exactly what you want.
In java, I want to get the number of days between two dates, excluding those two dates.
For example:
If first date = 11 November 2011 and the second date = 13 November 2011
then it should be 1.
This is the code I am using but doesn't work (secondDate and firstDate are Calendar objects):
long diff=secondDate.getTimeInMillis()-firstDate.getTimeInMillis();
float day_count=(float)diff / (24 * 60 * 60 * 1000);
daysCount.setText((int)day_count+"");
I even tried rounding the results but that didn't help.
How do I get the number of days between dates in java excluding the days themselves?
I've just tested on SDK 8 (Android 2.2) the following code snippet:
Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();
date1.clear();
date1.set(
datePicker1.getYear(),
datePicker1.getMonth(),
datePicker1.getDayOfMonth());
date2.clear();
date2.set(
datePicker2.getYear(),
datePicker2.getMonth(),
datePicker2.getDayOfMonth());
long diff = date2.getTimeInMillis() - date1.getTimeInMillis();
float dayCount = (float) diff / (24 * 60 * 60 * 1000);
textView.setText(Long.toString(diff) + " " + (int) dayCount);
it works perfectly and in both cases (Nov 10,2011 - Nov 8,2011) and (Nov 13,2011 - Nov 11,2011) gives dayCount = 2.0
Get Days between java.util.Dates, ignoring daylight savings time
Quick and dirty hack:
public int get_days_between_dates(Date date1, Date date2)
{
//if date2 is more in the future than date1 then the result will be negative
//if date1 is more in the future than date2 then the result will be positive.
return (int)((date2.getTime() - date1.getTime()) / (1000*60*60*24l));
}
This function will work 99.99% of the time, except when it surprises you later on in the edge cases during leap-seconds, daylight savings, timezone changes leap years and the like. If you are OK with the calculation being off by 1 (or 2) hours once in a while, this will suffice.
Get Days between Dates taking into account leapseconds, daylight savings, timezones, etc
If you are asking this question you need to slap yourself. What does it mean for two dates to be at least 1 day apart? It's very confusing. What if one Date is midnight in one timezone, and the other date is 1AM in another timezone? Depending on how you interpret it, the answer is both 1 and 0.
You think you can just force the dates you pass into the above function as Universal time format; that will fix some of your problems. But then you just relocate the problem into how you convert your local time to a universal time. The logical conversion from your timezone to universal time may not be what is intuitive. In some cases you will get a day difference when the dates passed in are obviously two days apart.
And you think you can deal with that? There are some simplistic calendar systems in the world which are constantly changing depending on the harvest season and installed political rulers. If you want to convert their time to UTC, java.util.Date is going to fail you at the worst moment.
If you need to calculate the days between dates and it is critical that everything come out right, you need to get an external library called Joda Time: (They have taken care of all the details for you, so you can stay blissfully unaware of them): http://joda-time.sourceforge.net/index.html
java.time
The java.time API, released with Java-8 in March 2014, supplanted the error-prone legacy date-time API. Since then, using this modern date-time API has been strongly recommended.
Solution using modern date-time API
Using Calendar#toInstant, convert your java.util.Calendar instances into java.time.Instant and then into java.time.ZonedDateTime instances and then use ChronoUnit.DAYS.between to get the number of days between them.
Demo:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
public class Main {
public static void main(String[] args) {
// Sample start and end dates as java.util.Date
Calendar startCal = Calendar.getInstance();
startCal.set(2011, 10, 11); // 11 November 2011
Calendar endCal = Calendar.getInstance();
endCal.set(2011, 10, 13); // 13 November 2011
// Convert the java.util.Calendar into java.time.ZonedDateTime
// Replace ZoneId.systemDefault() with the applicable ZoneId
ZonedDateTime startDateTime = startCal.toInstant().atZone(ZoneId.systemDefault());
ZonedDateTime endDateTime = endCal.toInstant().atZone(ZoneId.systemDefault());
// The end date is excluded by default. Subtract 1 to exclude the start date
long days = ChronoUnit.DAYS.between(startDateTime, endDateTime) - 1;
System.out.println(days);
}
}
Output:
1
Learn more about the modern Date-Time API from Trail: Date Time.
Don't use floats for integer calculations.
Are you sure your dates are days? The precision of the Date type is milliseconds. So the first thing you need to do is round the date to something which doesn't have hours. Example: It's just one hour from 23:30 2011-11-01 to 00:30 2011-11-02 but the two dates are on different days.
If you are only going to be dealing with dates between the years 1900 and 2100, there is a simple calculation which will give you the number of days since 1900:
public static int daysSince1900(Date date) {
Calendar c = new GregorianCalendar();
c.setTime(date);
int year = c.get(Calendar.YEAR);
if (year < 1900 || year > 2099) {
throw new IllegalArgumentException("daysSince1900 - Date must be between 1900 and 2099");
}
year -= 1900;
int month = c.get(Calendar.MONTH) + 1;
int days = c.get(Calendar.DAY_OF_MONTH);
if (month < 3) {
month += 12;
year--;
}
int yearDays = (int) (year * 365.25);
int monthDays = (int) ((month + 1) * 30.61);
return (yearDays + monthDays + days - 63);
}
Thus, to get the difference in days between two dates, you calculate their days since 1900 and calc the difference. Our daysBetween method looks like this:
public static Integer getDaysBetween(Date date1, Date date2) {
if (date1 == null || date2 == null) {
return null;
}
int days1 = daysSince1900(date1);
int days2 = daysSince1900(date2);
if (days1 < days2) {
return days2 - days1;
} else {
return days1 - days2;
}
}
In your case you would need to subtract an extra day (if the days are not equal).
And don't ask me where this calculation came from because we've used it since the early '90s.
I have two suggestions:
Make sure your float day_count is calculated correctly
float day_count = ((float)diff) / (24f * 60f * 60f * 1000f);
If it's rounding error, try using floor method
daysCount.setText("" + (int)Math.floor(day_count));
The time displayed is way ahead of what I expected. I'm parsing a date string and turning it into milliseconds.
year = Integer.parseInt(m1.group(1));
mo = Integer.parseInt(m1.group(2));
day = Integer.parseInt(m1.group(3));
hr = Integer.parseInt(m1.group(4));
min = Integer.parseInt(m1.group(5));
sec = Integer.parseInt(m1.group(6));
and here I set the Calendar
Calendar cal = Calendar.getInstance();
cal.set(year, mo, day, hr, min, sec);
time = cal.getTimeInMillis();
If you check out the calendar documentation here, then visit here, you'll see that January is month 0. You'll want to change your code to mo = Integer.parseInt(m1.group(2))-1;
You should probably use DateFormatter to parse the date string (rather than rolling your own).
Other than that, make sure that you have the proper time zone and understand that month number one is February (not January).