I want to ask if someone knows any API or something similar that allows me to manage concrete parts of day (for example working hours)
My problem is that I have to manage times in the next context:
imagine I am working in a company which working hours is "8am-2pm" and "3pm-6pm" and with a daylight saving time from "8am to 2pm". I want to know if a concrete moment of a concrete date is a laboral moment or if it isn't.
For example if I have the mentioned calendar, and I ask the API if the "13th august 2012 at 9pm" is a working moment it has to check it and return a correct answer (false in this case) and if I ask if the "13th august 2012 at 9am" is a working moment it has to return "true"
Other important thing related. I have to calculate intervals between two dates with the mentioned calendar. For example, if i set begin time as "today at 5pm" and end time "tomorrow at 10am" it has to return 3 hours (or its equivalent in seconds or milliseconds) because it is the correct time period passed between the begin date and the end date in this calendar.
It also has to work with holidays (particular of each country). I found an API call "JollyTime" but, although it works with holidays, it does not support the working hours...
Any idea?
Update: The Joda-Time library is now in maintenance-mode, its principal author Stephen Colebourne having gone on to lead JSR 310 that defines the java.time classes built into Java 8 and later.
A good database with sophisticated support for date-times may be of assistance here. One such database is Postgres, with good date-time data types and commands ("functions").
The Joda-Time framework may help as well. The Interval class and its parent classes define a span of time between a pair of start & stop date-times. They offer methods for comparison such as: contains, overlaps, isBefore, is After.
Here's some example code to get you started, using Joda-Time 2.3 with Java 7.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
List<Interval> workIntervalsFor13Aug2012 = new ArrayList<Interval>( 2 );
DateTime start, stop;
Interval interval;
start = new DateTime( 2012, 8, 13, 8, 0, 0, timeZone );
stop = new DateTime( 2012, 8, 13, 14, 0, 0, timeZone );
interval = new org.joda.time.Interval( start, stop );
workIntervalsFor13Aug2012.add( interval );
start = new DateTime( 2012, 8, 13, 15, 0, 0, timeZone );
stop = new DateTime( 2012, 8, 13, 18, 0, 0, timeZone );
interval = new org.joda.time.Interval( start, stop );
workIntervalsFor13Aug2012.add( interval );
// Check a date-time against those work intervals.
DateTime test09 = new DateTime( 2012, 8, 13, 9, 0, 0, timeZone );
DateTime test21 = new DateTime( 2012, 8, 13, 21, 0, 0, timeZone );
// You should write a "dateTimeIsInWorkingInterval" method that performs this loop.
Boolean hit = false;
for ( Interval nthInterval : workIntervalsFor13Aug2012 ) {
if( nthInterval.contains( test09 )) {
hit = true;
break;
}
}
if( hit ) {
System.out.println( "This date-time: " + test09 + " occurs during a work interval.");
} else {
System.out.println( "This date-time: " + test09 + " occurs outside a work interval.");
}
hit = false;
for ( Interval nthInterval : workIntervalsFor13Aug2012 ) {
if( nthInterval.contains( test21 )) {
hit = true;
break;
}
}
if( hit ) {
System.out.println( "This date-time: " + test21 + " occurs during a work interval.");
} else {
System.out.println( "This date-time: " + test21 + " occurs outside a work interval.");
}
When run…
This date-time: 2012-08-13T09:00:00.000+02:00 occurs during a work interval.
This date-time: 2012-08-13T21:00:00.000+02:00 occurs outside a work interval.
Take a look at the JODA Time library. I know it has intervals and might be just what you need.
I have implemented a simple solution to calculate working hours between two dates. Starting from this point of view may help you achieve your task.
Here is the class that calculates working time as minutes or miliseconds.
public class WorkingTime {
private static final long ONE_SECOND_AS_MILISECONDS = TimeUnit.SECONDS.convert(1, TimeUnit.SECONDS);
private Integer startHour;
private Integer endHour;
private Integer startMinute;
private Integer endMinute;
public WorkingTime(int startHour, int endHour) {
this(startHour, 0, endHour, 0);
}
public WorkingTime(Integer startHour, Integer startMinute,
Integer endHour, Integer endMinute) {
super();
this.startHour = startHour;
this.endHour = endHour;
this.startMinute = startMinute;
this.endMinute = endMinute;
}
... getters and setters
public long calculateWorkingAsMilis(Date date1, Date date2) {
return ONE_SECOND_AS_MILISECONDS * calculateWorkingSeconds(date1, date2);
}
public long calculateWorkingSeconds(Date date1, Date date2) {
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
setWorkingCalendar(cal1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
setWorkingCalendar(cal2);
long day1 = TimeUnit.MILLISECONDS.toDays(cal1.getTimeInMillis());
long day2 = TimeUnit.MILLISECONDS.toDays(cal2.getTimeInMillis());
long daydiff = day2 - day1;
long weekendDiff = (daydiff / 7); // get number of weekends
if (isLeakWeekend(cal1, cal2))
weekendDiff++;
long dailyWorkingTimeAsMinutes = getDailyWorkingTimeAsMinutes();
long secondsToBeDecrementedAsNonWorkingHours = TimeUnit.SECONDS.convert((24 * 60 - dailyWorkingTimeAsMinutes), TimeUnit.MINUTES); // seconds that are not in interval of working hours
long secondsToBeDecrementedAsWorkingHoursForWeekends = TimeUnit.SECONDS.convert(dailyWorkingTimeAsMinutes * 2, TimeUnit.MINUTES); // weekend is not working days, they need to be decremented
long dayDiffAsSeconds = daydiff * secondsToBeDecrementedAsNonWorkingHours;
dayDiffAsSeconds += (weekendDiff * secondsToBeDecrementedAsWorkingHoursForWeekends);
long workDiffSeconds = TimeUnit.SECONDS.convert(
cal2.getTimeInMillis() - cal1.getTimeInMillis(),
TimeUnit.MILLISECONDS) - dayDiffAsSeconds;
return workDiffSeconds;
}
private boolean isLeakWeekend(Calendar cal1, Calendar cal2) {
if (cal1.get(Calendar.DAY_OF_WEEK) > cal2.get(Calendar.DAY_OF_WEEK))
return true;
return false;
}
private long getDailyWorkingTimeAsMinutes() {
return (getEndHour() * 60 + getEndMinute()) - (getStartHour() * 60 + getStartMinute());
}
private Calendar setWorkingCalendar(Calendar cal) {
if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
cal.set(Calendar.DAY_OF_YEAR, cal.get(Calendar.DAY_OF_YEAR) + 1);
resetWorkingHourAndSeconds(cal);
} else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
cal.set(Calendar.DAY_OF_YEAR, cal.get(Calendar.DAY_OF_YEAR) + 2);
resetWorkingHourAndSeconds(cal);
} else if (cal.get(Calendar.HOUR_OF_DAY) > endHour || (cal.get(Calendar.HOUR_OF_DAY) == endHour && cal.get(Calendar.MINUTE) > endMinute)) {
cal.set(Calendar.HOUR_OF_DAY, endHour);
cal.set(Calendar.MINUTE, endMinute);
} else if (cal.get(Calendar.HOUR_OF_DAY) < startHour || (cal.get(Calendar.HOUR_OF_DAY) == startHour && cal.get(Calendar.MINUTE) < startMinute)) {
cal.set(Calendar.HOUR_OF_DAY, startHour);
cal.set(Calendar.MINUTE, startMinute);
}
return cal;
}
private Calendar resetWorkingHourAndSeconds(Calendar cal) {
cal.set(Calendar.HOUR_OF_DAY, startHour);
cal.set(Calendar.MINUTE, startMinute);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal;
}
}
And here is the usage
// create an instance (working hours from 08:30 to 17:30)
WorkingTime workingTime = new WorkingTime(8, 30, 17, 30);
long durationAsMilis = workingTime.calculateWorkingAsMilis(date1, date2);
Hope that helps
Tuncay Senturk
Related
In this method when passing 2020-03-01 as a date object the output is obtained as 2019-02-28. But I need it as 2020-02-29. The problem occurs only inputting date after 29th February in leap years.
public DateTime add(DateTime p_dateTime, int p_field, int p_amount) { //p_field = 1, p_amount = 1;
Calendar calendar = this.getCalendar(p_dateTime);
calendar.add(p_field, p_amount);
DateTime dateTime = this.getDateTime(calendar);
return dateTime;
}
Can I know what the problem is. Any advice?
The Calendar calendar object results shows like below.
java.util.GregorianCalendar[time = 1582910939192, areFieldsSet = true, areAllFieldsSet = true, lenient = true, zone = sun.util.calendar.ZoneInfo[id = "Asia/Colombo", offset = 19800000, dstSavings = 0, useDaylight = false, transitions = 9, lastRule = null], firstDayOfWeek = 2, minimalDaysInFirstWeek = 4, ERA = 1, YEAR = 2020, MONTH = 1, WEEK_OF_YEAR = 9, WEEK_OF_MONTH = 4, DAY_OF_MONTH = 28, DAY_OF_YEAR = 59, DAY_OF_WEEK = 6, DAY_OF_WEEK_IN_MONTH = 4, AM_PM = 1, HOUR = 10, HOUR_OF_DAY = 22, MINUTE = 58, SECOND = 59, MILLISECOND = 192, ZONE_OFFSET = 19800000, DST_OFFSET = 0]
I suggest that you do either of 2.:
If the DateTime class that you are using is the one from Joda-Time, go all-in on Joda-Time.
Migrate the whole thing to java.time, the modern Java date and time API.
In any case do not use the Calendar class. That class is poorly deigned and long outdated. And mixing different date-time libraries will just over-complicate things for you, so avoid doing that. To be honest I find that a method that takes a Joda-Time DateTime and a field number from Calendar as arguments is a bad design.
Joda-Time
A design of your method for Joda-Time may look like this:
public static DateTime add(DateTime pDateTime, DurationFieldType pField, int pAmount) {
return pDateTime.withFieldAdded(pField, pAmount);
}
Please enjoy how much simpler it is compared to the method in the question. We may use the method for example in this way:
DateTime now = DateTime.now(DateTimeZone.forID("Asia/Colombo"));
DateTime oneYearLater = add(now, DurationFieldType.years(), 1);
System.out.println("Now = " + now + ". Next year = " + oneYearLater + ' ');
Output when I ran the code just now was:
Now = 2020-05-25T09:14:19.880+05:30. Next year = 2021-05-25T09:14:19.880+05:30
java.time
The java.time code is similar, though maybe a bit more easy to read:
public static ZonedDateTime add(ZonedDateTime pDateTime, TemporalUnit pField, int pAmount) {
return pDateTime.plus(pAmount, pField);
}
Use like this:
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Colombo"));
ZonedDateTime oneYearLater = add(now, ChronoUnit.YEARS, 1);
System.out.println("Now = " + now + ". Next year = " + oneYearLater + ' ');
Now = 2020-05-25T09:14:39.732386+05:30[Asia/Colombo]. Next year = 2021-05-25T09:14:39.732386+05:30[Asia/Colombo]
Links
Documentation of Joda-Time DateTime.withFieldsAdded()
Oracle tutorial: Date Time explaining how to use java.time.
I have a Do Not Disturb system that mutes the sounds of my android app if the current time is in Do not disturb range time.
It works fine if I use a range time just between a day, but I dont know how to write it with one day off, For example at 11:00 pm to 1:00 am of the next day.
This is method that I used for detecting DND time:
private boolean isInDNDTime() {
Calendar now = Calendar.getInstance();
Calendar startTime = Calendar.getInstance();
Calendar endTime = Calendar.getInstance();
MyDate myDate = new MyDate(new Date());
if (isDNDTwoDays()) {
startTime.setTime(myDate.getYesterday().toDate());
startTime.set(Calendar.HOUR_OF_DAY, getDNDStartHourTime());
startTime.set(Calendar.MINUTE, getDNDStartMinuteTime());
endTime.setTime(myDate.getTomorrow().toDate());
endTime.set(Calendar.HOUR_OF_DAY, getDNDEndHourTime());
endTime.set(Calendar.MINUTE, getDNDEndMinuteTime());
} else {
startTime.set(Calendar.HOUR_OF_DAY, getDNDStartHourTime());
startTime.set(Calendar.MINUTE, getDNDStartMinuteTime());
endTime.set(Calendar.HOUR_OF_DAY, getDNDEndHourTime());
endTime.set(Calendar.MINUTE, getDNDEndMinuteTime());
}
return now.after(startTime) && now.before(endTime);
}
Pls try below code
private boolean isInDNDTime() {
Calendar now = Calendar.getInstance();
Calendar startTime = Calendar.getInstance();
Calendar endTime = Calendar.getInstance();
MyDate myDate = new MyDate(new Date());
if (isDNDTwoDays()) {
startTime.add(Calendar.DATE, 1);
endTime.add(Calendar.DATE, 1);
// startTime.setTime(myDate.getYesterday().toDate());
startTime.set(Calendar.HOUR_OF_DAY, getDNDStartHourTime());
startTime.set(Calendar.MINUTE, getDNDStartMinuteTime());
// endTime.setTime(myDate.getTomorrow().toDate());
endTime.set(Calendar.HOUR_OF_DAY, getDNDEndHourTime());
endTime.set(Calendar.MINUTE, getDNDEndMinuteTime());
} else {
startTime.set(Calendar.HOUR_OF_DAY, getDNDStartHourTime());
startTime.set(Calendar.MINUTE, getDNDStartMinuteTime());
endTime.set(Calendar.HOUR_OF_DAY, getDNDEndHourTime());
endTime.set(Calendar.MINUTE, getDNDEndMinuteTime());
}
return now.after(startTime) && now.before(endTime);
}
There is a modern API for tasks like this, it is called java.time and is available from Java 8. The following example illustrates how to do that with a few lines of code:
public static void main(String[] args) {
// create sample data
LocalDateTime start = LocalDateTime.of(2020, 2, 19, 12, 30);
LocalDateTime timeInDND = LocalDateTime.now();
LocalDateTime end = LocalDateTime.of(2020, 2, 21, 12, 30);
// just check if the time is equal to start or end or is between them
if (timeInDND.equals(start) || timeInDND.equals(end)
|| (timeInDND.isAfter(start) && timeInDND.isBefore(end))) {
System.out.println(timeInDND.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
+ " is in the DND period");
} else {
System.err.println(timeInDND.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
+ " is not in the DND period");
}
}
Unfortunately, your support of Android API levels below 26 requires an external library, the ThreeTen Android Backport because java.time is available from API level 26. You can check another question about how to use the ThreeTenABP.
I want to compare two dates for my Android application, but I got a really weird issue.
For example:
If I set the back in the past date to 127 days ago:
this.dateEvent = System.currentTimeMillis() - (127 * 24 * 3600 * 1000)
And then compare it to the current date (Days between)
Calendar sDate = getDatePart(new Date(this.dateEvent));
Calendar eDate = getDatePart(new Date(System.currentTimeMillis()));
int daysBetween = 0;
while (sDate.before(eDate))
{
sDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween ++;
}
while (sDate.after(eDate))
{
eDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween ++;
}
return daysBetween;
It will return 22 which is not at all what was expected.
Did I make something wrong or is that an issue with the Calendar class ?
Here's a two line solution:
long msDiff = Calendar.getInstance().getTimeInMillis() - testCalendar.getTimeInMillis();
long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);
In this example it gets the number of days between date "testCalendar" and the current date.
Please refer this code, this may help you.
public String getCountOfDays(String createdDateString, String expireDateString) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());
Date createdConvertedDate = null, expireCovertedDate = null, todayWithZeroTime = null;
try {
createdConvertedDate = dateFormat.parse(createdDateString);
expireCovertedDate = dateFormat.parse(expireDateString);
Date today = new Date();
todayWithZeroTime = dateFormat.parse(dateFormat.format(today));
} catch (ParseException e) {
e.printStackTrace();
}
int cYear = 0, cMonth = 0, cDay = 0;
if (createdConvertedDate.after(todayWithZeroTime)) {
Calendar cCal = Calendar.getInstance();
cCal.setTime(createdConvertedDate);
cYear = cCal.get(Calendar.YEAR);
cMonth = cCal.get(Calendar.MONTH);
cDay = cCal.get(Calendar.DAY_OF_MONTH);
} else {
Calendar cCal = Calendar.getInstance();
cCal.setTime(todayWithZeroTime);
cYear = cCal.get(Calendar.YEAR);
cMonth = cCal.get(Calendar.MONTH);
cDay = cCal.get(Calendar.DAY_OF_MONTH);
}
/*Calendar todayCal = Calendar.getInstance();
int todayYear = todayCal.get(Calendar.YEAR);
int today = todayCal.get(Calendar.MONTH);
int todayDay = todayCal.get(Calendar.DAY_OF_MONTH);
*/
Calendar eCal = Calendar.getInstance();
eCal.setTime(expireCovertedDate);
int eYear = eCal.get(Calendar.YEAR);
int eMonth = eCal.get(Calendar.MONTH);
int eDay = eCal.get(Calendar.DAY_OF_MONTH);
Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();
date1.clear();
date1.set(cYear, cMonth, cDay);
date2.clear();
date2.set(eYear, eMonth, eDay);
long diff = date2.getTimeInMillis() - date1.getTimeInMillis();
float dayCount = (float) diff / (24 * 60 * 60 * 1000);
return ("" + (int) dayCount + " Days");
}
I've finally found the easiest way to deal with that. Here is my code:
public int getTimeRemaining()
{
Calendar sDate = toCalendar(this.dateEvent);
Calendar eDate = toCalendar(System.currentTimeMillis());
// Get the represented date in milliseconds
long milis1 = sDate.getTimeInMillis();
long milis2 = eDate.getTimeInMillis();
// Calculate difference in milliseconds
long diff = Math.abs(milis2 - milis1);
return (int)(diff / (24 * 60 * 60 * 1000));
}
private Calendar toCalendar(long timestamp)
{
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar;
}
Hope it helps.
You should never use formula such 24 * 60 * 60 * 1000! Why? Because there is day saving time, and not all days have 24 hours, also what about leap year, that has +1 day. That's why there is a calendar class.
If you do not want to put any external library to your project like Jodatime, you could use pure Calendar class with very efficient function:
public static int numDaysBetween(final Calendar c, final long fromTime, final long toTime) {
int result = 0;
if (toTime <= fromTime) return result;
c.setTimeInMillis(toTime);
final int toYear = c.get(Calendar.YEAR);
result += c.get(Calendar.DAY_OF_YEAR);
c.setTimeInMillis(fromTime);
result -= c.get(Calendar.DAY_OF_YEAR);
while (c.get(Calendar.YEAR) < toYear) {
result += c.getActualMaximum(Calendar.DAY_OF_YEAR);
c.add(Calendar.YEAR, 1);
}
return result;
}
public long Daybetween(String date1,String date2,String pattern)
{
SimpleDateFormat sdf = new SimpleDateFormat(pattern,Locale.ENGLISH);
Date Date1 = null,Date2 = null;
try{
Date1 = sdf.parse(date1);
Date2 = sdf.parse(date2);
}catch(Exception e)
{
e.printStackTrace();
}
return (Date2.getTime() - Date1.getTime())/(24*60*60*1000);
}
Date userDob = new SimpleDateFormat("yyyy-MM-dd").parse(dob);
Date today = new Date();
long diff = today.getTime() - userDob.getTime();
int numOfYear = (int) ((diff / (1000 * 60 * 60 * 24))/365);
int numOfDays = (int) (diff / (1000 * 60 * 60 * 24));
int hours = (int) (diff / (1000 * 60 * 60));
int minutes = (int) (diff / (1000 * 60));
int seconds = (int) (diff / (1000));
I had the same need, I finally ended up using Joda Time, it is very convenient and offers lots of additional functions including the one you are looking for.
You can download the files from here.
Once you included the jar file into your project, you can easily do for example the following:
int daysBetween = Days.daysBetween(new DateTime(sDate), new DateTime(eDate)).getDays();
the best way :-
long fromCalender = Calender.getInstance();
fromCalender.set...// set the from dates
long toCalender = Calender.getInstance();
fromCalender.set...// set the to dates
long diffmili = fromCalender - toCalender;
long hours = TimeUnit.MILLISECONDS.toHours(diffmili);
long days = TimeUnit.MILLISECONDS.toDays(diffmili);
long min = TimeUnit.MILLISECONDS.toMinutes(diffmili);
long sec = TimeUnit.MILLISECONDS.toSeconds(diffmili);
Do like this it supports all Api Levels
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy HH:mm:ss",
Locale.ENGLISH);
try {
String datestart="June 14 2018 16:02:37";
cal.setTime(sdf.parse(datestart));// all done
Calendar cal1=Calendar.getInstance();
String formatted = sdf.format(cal1.getTime());//formatted date as i want
cal1.setTime(sdf.parse(formatted));// all done
long msDiff = cal1.getTimeInMillis() - cal.getTimeInMillis();
long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);
Toast.makeText(this, "days="+daysDiff, Toast.LENGTH_SHORT).show();
} catch (ParseException e) {
e.printStackTrace();
}
fun TimeZone.daysBetween(from: Date, to: Date): Int {
val offset = rawOffset + dstSavings
return ((to.time + offset) / 86400000).toInt() - ((from.time + offset) / 86400000).toInt()
}
Have a try:
val f = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").apply {
timeZone = TimeZone.getTimeZone("GMT")
}
val df = f.parse("2019-02-28 22:59:59")
val dt = f.parse("2019-02-28 23:00:00")
TimeZone.getTimeZone("GMT").daysBetween(df, dt) // 0
TimeZone.getTimeZone("GMT+1").daysBetween(df, dt) // 1
java.time and ThreeTenABP
I should like to contribute the modern answer: Use java.time, the modern Java date and time API for your date work. If developing for Android API level 25 or lower, then through the backport for Android, ThreeTenABP (link at the bottom).
LocalDate eDate = LocalDate.now(ZoneId.of("Europe/Paris"));
LocalDate sDate = eDate.minusDays(127);
long daysBetween = ChronoUnit.DAYS.between(sDate, eDate);
System.out.println(daysBetween);
When I ran this code today, the output was the expected:
127
Notice that the code is not only shorter, just one line for finding the difference; it is also clearer and more natural to read. The classes Date and Calendar that you used are poorly designed and long outdated. I recommend you don’t use them.
What went wrong in your code?
You’ve got an int overflow in your conversion of 127 days to milliseconds. In mathematics 127 * 24 * 3600 * 1000 equals 10 972 800 000. Since the numbers you multiply are ints, Java performs the multiplication in int, and the largest number an int can hold is 2 147 483 647, far from enough for your expected result. In this situation it would have been nice if Java would have thrown an exception or in some other way have made us aware of the error. It doesn’t. It tacitly throws away the high order bits, giving us a result of -1 912 101 888. Subtracting this negative number from the current time is equivalent to adding 22 days and a few hours. This explains why you got 22. Funny that 13 answers have been posted and it seems that no one has spotted this …
Even when doing the multiplication using the long type, it still doesn’t calculate 127 days correctly, though. If the 127 days cross a transition to or from summer time (DST), which in France is the case during 254 of the 365 days of a year, the day of the transition is not 24 hours, but either 23 or 25. Which causes an incorrect number of milliseconds.
You should always leave date math to proven library methods. Never hand code it yourself. It’s more complicated than most of us think, so the risk of doing it incorrectly is high.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
The best solution that worked for me is :
private static int findDaysDiff(long unixStartTime,long unixEndTime)
{
Calendar calendar1 = Calendar.getInstance();
calendar1.setTimeInMillis(unixStartTime);
calendar1.set(Calendar.HOUR_OF_DAY, 0);
calendar1.set(Calendar.MINUTE, 0);
calendar1.set(Calendar.SECOND, 0);
calendar1.set(Calendar.MILLISECOND, 0);
Calendar calendar2 = Calendar.getInstance();
calendar2.setTimeInMillis(unixEndTime);
calendar2.set(Calendar.HOUR_OF_DAY, 0);
calendar2.set(Calendar.MINUTE, 0);
calendar2.set(Calendar.SECOND, 0);
calendar2.set(Calendar.MILLISECOND, 0);
return (int) ((calendar2.getTimeInMillis()-calendar1.getTimeInMillis())/(24 * 60 * 60 * 1000));
}
Since it first converts Hour , Minute, Second and Millisecond to 0 and now the difference will be only in days.
the answer is not correct in some dates like "2019/02/18" , "2019/02/19" but i edit and resolve bug
this is best method :
public int getCountOfDays(String createdDateString, String expireDateString) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date createdConvertedDate = null;
Date expireCovertedDate = null;
try {
createdConvertedDate = dateFormat.parse(createdDateString);
expireCovertedDate = dateFormat.parse(expireDateString);
} catch (ParseException e) {
e.printStackTrace();
}
Calendar start = new GregorianCalendar();
start.setTime(createdConvertedDate);
Calendar end = new GregorianCalendar();
end.setTime(expireCovertedDate);
long diff = end.getTimeInMillis() - start.getTimeInMillis();
float dayCount = (float) diff / (24 * 60 * 60 * 1000);
return (int) (dayCount);
}
Enjoy and if was helpefull +vote to this answer ;)
Kotlin Extension:
fun Date?.getDaysBetween(dest: Date?): Int {
if(this == null || dest == null) return 0
val diff = abs(this.time - dest.time)
val dayCount = diff.toFloat() / (24 * 60 * 60 * 1000)
return dayCount.toInt()
}
I am count the days between last submission date and current date if it is less than zero then student cannot give submission. I am working with kotlin. The below code helps you.
var calendar=Calendar.getInstance().time
var dateFormat= SimpleDateFormat("dd/M/yyyy")
var d2=dateFormat.parse(data.get("date").toString())
var cd=dateFormat.format(calendar)
var d1=dateFormat.parse(cd)
var diff=d2.time-d1.time
var ddd= TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS)
This is the Java 8 java.time version which works perfectly for me. You might want to make sure that startDate and endDate are set to the same time, otherwise days might vary by +-1!
These are the Kotlin versions I just copy/pasted.
private fun getDawnOfDay(instant: Instant): Temporal =
LocalDate.from(instant.atZone(ZoneOffset.UTC)).atStartOfDay()
fun getNumberOfDaysInBetween(startDate: Date, endDate: Date) =
Duration.between(getDawnOfDay(startDate.toInstant()), getDawnOfDay(endDate.toInstant()))
.toDays()
I have just modified a little bit most popular answer.
Here is my solution:
daysBetween() - Return days count between two dates.
public static long daysBetween(Date date1, Date date2) {
long msDiff = resetTimeToDateStart(date1).getTime() - resetTimeToDateStart(date2).getTime();
return TimeUnit.MILLISECONDS.toDays(msDiff);
}
private static Date resetTimeToDateStart(Date dDate){
if (Utils.isNull(dDate)){
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(dDate);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
int difference in days=(present_year - oldyear) * 365 + (present_month - oldmonth)*30 + (present_date-olddate);
All above answers calculating millis_diff / (24 * 60 * 60 * 1000) is simply wrong if you consider 23:59:59 ~ 00:00:00 as two different days and expect offset day count as 1, instead of 0.
A kotlin version gives you count 1, based on #oleksandr-albul answer above.
fun getDayCountBetween(to: Long, from: Long): Int {
if (to <= from) return 0
val calendar = Calendar.getInstance()
var count = 0
// get day count between 'to' and Jan 1st.
calendar.timeInMillis = to
val year = calendar.get(Calendar.YEAR)
count += calendar.get(Calendar.DAY_OF_YEAR)
// minus day count between 'from' and Jan 1st.
calendar.timeInMillis = from
count -= calendar.get(Calendar.DAY_OF_YEAR)
// plus day count of all the gap years.
while (calendar.get(Calendar.YEAR) < year) {
count += calendar.getActualMaximum(Calendar.DAY_OF_YEAR)
calendar.add(Calendar.YEAR, 1)
}
return count
}
I create J2SE application and this application needs to format two times in milliseconds into a string that represents the interval between this two times.
long time1 = 1334331041677L; //Fri Apr 13 17:30:41 CEST 2012
long time2 = time1+1000*60*2; //Fri Apr 13 17:32:41 CEST 2012
and I would like to get something like "00:02:00". This would be simple, but I need to format interval which is long from few seconds up to several years - so the library should handle it. Ideally is if this library could format the interval according to the habbits of the country (if any).
I have searched throught the questions and answers and solution for me could be Jodatime or Lang library from Apache Commons. Could you provide me some recommendation which library from these solves my requirements in better way? Thank you in advance.
PeriodFormat in Joda Time is probably what you want - but you'll need to think very carefully about how you want to format values of more than a day. Bear in mind that months and years are of variable lengths - if you're happy to have the largest unit as a day, that would probably keep things simple.
You should also be aware of the difference in Joda Time between a Period (which can include things like "months") and a Duration which is a fixed number of milliseconds. Normalization between the two touches on exactly the problems mentioned above :) Basically, you should work out whether you're interested in the difference in elapsed time between two instants in time, or the difference in "calendar" time between two local date/time values. For example, between midnight and 2am on a particular date in a particular time zone may be 1 hour, 2 hours or 3 hours of elapsed time...
You can use standard Java Calendar for intervals up to one day (24 hours). It is not possible to use this trick for longer periods (days, years), though...
long start = System.currentTimeMillis();
/*
* perform the measured activity here,
* let's say it will take 2 minutes 5 seconds => 125 seconds => 125000ms
*/
Thread.sleep(125 * 1000);
long stop = System.currentTimeMillis();
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
c.setTimeInMillis(c.getTimeInMillis() + (stop - start));
DateFormat df = new SimpleDateFormat("HH:mm:ss.SSS");
System.out.println(df.format(c.getTime()));
If I understood you correctly, the following (using Joda Time) should help
import org.joda.time.DateTime;
import org.joda.time.Period;
private String formatDuration(DateTime dt1, DateTime dt2) {
Period period = new Period(dt1, dt2);
String str = String.format("%s:%02d:%02d:%02d:%02d:%02d",
period.getYears(), period.getMonths(), period.getDays(),
period.getHours(), period.getMinutes(), period.getSeconds());
// Ignoring milliseconds
String[] tokens = str.split(":");
boolean currNonZero = false, flag = false, isFirst = true;
int ctr = 0, pos = 0;
StringBuilder sb = new StringBuilder();
for (String token : tokens) {
pos++;
int val = Integer.parseInt(token);
currNonZero = (val > 0);
if ((ctr < 3 && (flag || currNonZero)) || (ctr == 0 && pos > 3)) {
if (isFirst) { isFirst = false; }
else { sb.append(":"); }
sb.append(token);
flag = (++ctr < 3);
}
}
return sb.toString();
}
A few tests,
DateTime dt1 = new DateTime(2012, 1, 1, 8, 3, 5, 0);
DateTime dt2 = new DateTime(2012, 1, 2, 9, 5, 6, 0);
DateTime dt3 = new DateTime(2012, 2, 3, 11, 3, 5, 0);
DateTime dt4 = new DateTime(2012, 2, 3, 11, 3, 10, 0);
DateTime dt5 = new DateTime(2012, 2, 3, 11, 3, 10, 5); //5 millis away from dt4
formatDuration(dt1, dt2); // Returns "01:01:01"
formatDuration(dt1, dt3); // Returns "01:02:03"
formatDuration(dt3, dt4); // Returns "00:00:05"
formatDuration(dt4, dt5); // Returns "00:00:00"
According to this answer, this is the most efficient way of formatting elapsed time:
public static String combinationFormatter(final long millis) {
long seconds = TimeUnit.MILLISECONDS.toSeconds(millis)
- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis));
long minutes = TimeUnit.MILLISECONDS.toMinutes(millis)
- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis));
long hours = TimeUnit.MILLISECONDS.toHours(millis);
StringBuilder b = new StringBuilder();
b.append(hours == 0 ? "00" : hours < 10 ? String.valueOf("0" + hours) :
String.valueOf(hours));
b.append(":");
b.append(minutes == 0 ? "00" : minutes < 10 ? String.valueOf("0" + minutes) :
String.valueOf(minutes));
b.append(":");
b.append(seconds == 0 ? "00" : seconds < 10 ? String.valueOf("0" + seconds) :
String.valueOf(seconds));
return b.toString();
}
Detailed Answer: https://stackoverflow.com/a/39600534/5330578
Simple formatting for elapsed time less than 24h. Over 24h the code will only display the hours within the next day and won't add the elapsed day to the hours.
public static String formatElapsedTime(long milliseconds) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
return sdf.format(milliseconds);
}
Im working in a project and I got two types in Date. I want to calculate the number of weeks between these two dates. The dates can be in diffrent years. Is there any good solution for this?
I have tried to implemenent this with Joda-time which was suggested in other topics..
Im not familar with this library, but I tried to do something like this:
public static int getNumberOfWeeks(Date f, Date l){
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c1.setTime(f);
c2.setTime(l);
DateTime start = new DateTime(c1.YEAR, c1.MONTH, c1.DAY_OF_MONTH, 0, 0, 0, 0);
DateTime end = new DateTime(c2.YEAR, c2.MONTH, c2.DAY_OF_MONTH, 0, 0, 0, 0);
Interval interval = new Interval(start, end);
Period p = interval.toPeriod();
return p.getWeeks();
}
But this is completely wrong... any suggestions ?
Updating answer to account for Java 8
// TechTrip - ASSUMPTION d1 is earlier than d2
// leave that for exercise
public static long getFullWeeks(Calendar d1, Calendar d2){
Instant d1i = Instant.ofEpochMilli(d1.getTimeInMillis());
Instant d2i = Instant.ofEpochMilli(d2.getTimeInMillis());
LocalDateTime startDate = LocalDateTime.ofInstant(d1i, ZoneId.systemDefault());
LocalDateTime endDate = LocalDateTime.ofInstant(d2i, ZoneId.systemDefault());
return ChronoUnit.WEEKS.between(startDate, endDate);
}
It is pretty easy with joda time:
DateTime dateTime1 = new DateTime(date1);
DateTime dateTime2 = new DateTime(date2);
int weeks = Weeks.weeksBetween(dateTime1, dateTime2).getWeeks();
tl;dr
ChronoUnit
.WEEKS
.between(
myJavaUtilDate_Start.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) ) ,
myJavaUtilDate_Stop.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) )
)
7
java.time
The java.time framework is built into Java 8 and later. These new classes supplant the old date-time classes bundled with the earliest versions of Java.
The java.time classes also supplant the highly successful Joda-Time framework. Both java.time and Joda-Time are led by Stephen Colbourne.
Instant replaces java.util.Date
The modern class Instant replaces the legacy class java.util.Date. Both represent a moment in UTC, a specific point on the timeline. Both internally use a count since the same epoch reference of the first moment of 1970 in UTC, 1970-01-01T00:00Z. The old class uses a count of milliseconds, while Instant uses a finer count of nanoseconds.
To convert, call new methods added to the old classes.
Instant start = myJavaUtilDateStart.toInstant() ;
Instant stop = myJavaUtilDateStop.toInstant() ;
Let's make this concrete with some example values.
Instant start = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).toInstant();
Instant stop = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).plusWeeks(7 ).toInstant();
Moments versus dates
Both of our Instant objects represent a moment. The goal is a count of weeks. Weeks means days, and days mean certain dates on the calendar.
So we have a bit of a mismatch. For any given moment, the date varies around the globe by time zone. A few minutes after midnight in Paris France is a new date. Meanwhile in Montréal Québec, being several hours behind, that same moment is still “yesterday”, the date before on the calendar. So we cannot directly calculate weeks from a pair of moments.
You must first decide on the time zone by which you want to perceive a calendar for those moments.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime
Apply this ZoneId to our Instant objects to adjust into a time zone, yielding a pair of ZonedDateTime objects.
ZonedDateTime startZdt = start.atZone( z ) ;
ZonedDateTime stopZdt = stop.atZone( z ) ;
ChronoUnit.WEEKS
Now we can use the ChronoUnit enum to calculate elapsed weeks.
long weeks = ChronoUnit.WEEKS.between( startZdt , stopZdt );
Dump to console.
System.out.println( "start.toString() = " + start );
System.out.println( "stop.toString() = " + stop );
System.out.println( "startZdt.toString() = " + startZdt );
System.out.println( "stopZdt.toString() = " + stopZdt );
System.out.println( "weeksCount: " + weeksCount );
See this code run live at IdeOne.com.
start.toString() = 2020-01-23T15:30:00Z
stop.toString() = 2020-03-12T15:30:00Z
startZdt.toString() = 2020-01-23T10:30-05:00[America/Montreal]
stopZdt.toString() = 2020-03-12T11:30-04:00[America/Montreal]
weeksCount: 7
ThreeTen-Extra
The ThreeTen-Extra project adds functionality to the java.time framework built into Java 8 and later.
Weeks class
That project includes a Weeks class to represent a number of weeks. Not only can it calculate, it is also meant to be used in your code as a type-safe object. Such use also helps to make your code self-documenting.
You can instantiate by providing a pair of points in time with the Weeks.between method. Those points in time can be anything implementing java.time.temporal.Temporal including Instant, LocalDate, OffsetDateTime, ZonedDateTime, Year, YearMonth, and more.
Your java.util.Date objects can be easily converted to Instant objects, moments on the timeline in UTC with a resolution in nanoseconds. Look at new methods added to the old date-time classes. For going from Date to Instant, call java.util.Date::toInstant.
Weeks weeks = Weeks.between( startZdt , stopZdt );
You can ask for the number of weeks.
int weeksNumber = weeks.getAmount(); // The number of weeks in this Weeks object.
You can also do much more.
Generate a string in standard ISO 8601 format. The P marks the beginning. The W indicates a number of weeks.
PW7
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Using the date arithmetic in java.util.Calendar:
public static int getWeeksBetween (Date a, Date b) {
if (b.before(a)) {
return -getWeeksBetween(b, a);
}
a = resetTime(a);
b = resetTime(b);
Calendar cal = new GregorianCalendar();
cal.setTime(a);
int weeks = 0;
while (cal.getTime().before(b)) {
// add another week
cal.add(Calendar.WEEK_OF_YEAR, 1);
weeks++;
}
return weeks;
}
public static Date resetTime (Date d) {
Calendar cal = new GregorianCalendar();
cal.setTime(d);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
If your requirement is like the start date is 03-Apr-2020 and end date is 07-Apr-2020. the difference between the two dates is 4 days. Now the number of weeks between two dates as 1 for this you can use below snippet.
ChronoUnit.WEEKS.between(LocalDate startDate, LocalDate endDate);
But If your requirement is like 03-Apr-2020 is in one week and 07-Apr-2020 is in another week so you want the number of weeks between two dates as 2 you can use the below snippet.
LocalDate actualStartDate=...
LocalDate actualEndDate=...
LocalDate startDate = actualStartDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY))
LocalDate endDate = actualEndDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SATURDAY))
long daysBetweenTwoDates = ChronoUnit.DAYS.between(startDate, endDate);
int numberOfWeeks = (int)Math.ceil(daysBetweenTwoDates/7.0);
Tested in java 1.8
Calendar a = new GregorianCalendar(2002,1,22);
Calendar b = new GregorianCalendar(2002,1,28);
System.out.println(a.get(Calendar.WEEK_OF_YEAR));
System.out.println(b.get(Calendar.WEEK_OF_YEAR));
int weeks = b.get(Calendar.WEEK_OF_YEAR)-a.get(Calendar.WEEK_OF_YEAR);
System.out.println(weeks);
try this must work
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.set(2007, 01, 10);
calendar2.set(2007, 07, 01);
long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
int diffWeeks = (int)diff / (7*24 * 60 * 60 * 1000);
Here are 2 methods I wrote that not based on an external library.
The first method is when Monday is the first day of the week.
The second method is when Sunday is the first day of the week.
Please read the comments inside the code, there is an option to return the number of the full weeks between 2 dates, and also with the fraction of the remaining days before and after the 2 dates.
public static int getNumberOfFullWeeks(LocalDate startDate,LocalDate endDate)
{
int dayBeforeStartOfWeek = 0;
int daysAfterLastFullWeek = 0;
if(startDate.getDayOfWeek() != DayOfWeek.MONDAY)
{
// get the partial value before loop starting
dayBeforeStartOfWeek = 7-startDate.getDayOfWeek().getValue() + 1;
}
if(endDate.getDayOfWeek() != DayOfWeek.SUNDAY)
{
// get the partial value after loop ending
daysAfterLastFullWeek = endDate.getDayOfWeek().getValue();
}
LocalDate d1 = startDate.plusDays(dayBeforeStartOfWeek); // now it is the first day of week;
LocalDate d2 = endDate.minusDays(daysAfterLastFullWeek); // now it end in the last full week
// Count how many days there are of full weeks that start on Mon and end in Sun
// if the startDate and endDate are less than a full week the while loop
// will not iterate at all because d1 and d2 will be the same date
LocalDate looper = d1;
int counter = 1;
while (looper.isBefore(d2))
{
counter++;
looper = looper.plusDays(1);
}
// Counter / 7 will always be an integer that will represents full week
// because we started to count at Mon and stop counting in Sun
int fullWeeks = counter / 7;
System.out.println("Full weeks between dates: "
+ fullWeeks + " Days before the first monday: "
+ dayBeforeStartOfWeek + " "
+ " Days after the last sunday: " + daysAfterLastFullWeek);
System.out.println(startDate.toString() + " - " + endDate.toString());
// You can also get a decimal value of the full weeks plus the fraction if the days before
// and after the full weeks
float full_weeks_decimal = (float)fullWeeks;
float fraction = ((float)dayBeforeStartOfWeek + (float)daysAfterLastFullWeek) / 7.0F;
System.out.println("Full weeks with fraction: " + String.valueOf(fraction + full_weeks_decimal));
return fullWeeks;
}
public static int getNumberOfFullWeeks_WeekStartAtSunday(LocalDate startDate,LocalDate endDate)
{
int dayBeforeStartOfWeek = 0;
int daysAfterLastFullWeek = 0;
if(startDate.getDayOfWeek() != DayOfWeek.SUNDAY)
{
// get the partial value before loop starting
dayBeforeStartOfWeek = 7-getDayOfWeekBySundayIs0(startDate.getDayOfWeek()) + 1;
}
if(endDate.getDayOfWeek() != DayOfWeek.SATURDAY)
{
// get the partial value after loop ending
daysAfterLastFullWeek = 1+getDayOfWeekBySundayIs0(endDate.getDayOfWeek());
}
LocalDate d1 = startDate.plusDays(dayBeforeStartOfWeek); // now it is the first day of week;
LocalDate d2 = endDate.minusDays(daysAfterLastFullWeek); // now it end in the last full week
// Count how many days there are of full weeks that start on Sun and end in Sat
// if the startDate and endDate are less than a full week the while loop
// will not iterate at all because d1 and d2 will be the same date
LocalDate looper = d1;
int counter = 1;
while (looper.isBefore(d2))
{
counter++;
looper = looper.plusDays(1);
}
// Counter / 7 will always be an integer that will represents full week
// because we started to count at Sun and stop counting in Sat
int fullWeeks = counter / 7;
System.out.println("Full weeks between dates: "
+ fullWeeks + " Days before the first sunday: "
+ dayBeforeStartOfWeek + " "
+ " Days after the last saturday: " + daysAfterLastFullWeek);
System.out.println(startDate.toString() + " - " + endDate.toString());
// You can also get a decimal value of the full weeks plus the fraction if the days before
// and after the full weeks
float full_weeks_decimal = (float)fullWeeks;
float fraction = ((float)dayBeforeStartOfWeek + (float)daysAfterLastFullWeek) / 7.0F;
System.out.println("Full weeks with fraction: " + String.valueOf(fraction + full_weeks_decimal));
return fullWeeks;
}
public static int getDayOfWeekBySundayIs0(DayOfWeek day)
{
if(day == DayOfWeek.SUNDAY)
{
return 0;
}
else
{
// NOTE: getValue() is starting to count from 1 and not from 0
return day.getValue();
}
}
If you want exact number of full weeks use below method, where end date is exclusive:
public static long weeksBetween(Date date1, Date date2) {
return WEEKS.between(date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
}
If you want a ceil version of this, use below:
public static long weeksBetween(Date date1, Date date2) {
long daysBetween = DAYS.between(date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()) + 1;
return daysBetween / 7 + (daysBetween % 7 == 0 ? 0 : 1);
}
You may do it the following way:
// method header not shown
// example dates:
f = new GregorianCalendar(2009,Calendar.AUGUST,1);
l = new GregorianCalendar(2010,Calendar.SEPTEMBER,1);
DateTime start = new DateTime(f);
DateTime end = new DateTime(l);
// Alternative to above - example dates with joda:
// DateTime start = new DateTime(2009,8,1,0,0,0,0);
// DateTime end = new DateTime(2010,9,1,0,0,0,0);
Interval interval = new Interval(start,end);
int weeksBetween = interval.toPeriod(PeriodType.weeks()).getWeeks();
// return weeksBetween;
This should give you an int representing the number of weeks between the two dates.
Joda Time computes weeks with durations of two dates which may not meet our requirements in some cases. I have a method with Joda Time to compute natural weeks between two dates. Hope it can help you. If you don't use Joda Time, you may modify the code with Calendar to do the same thing.
//Unlike Joda Time Weeks.weeksBetween() that returns whole weeks computed
//from duration, we return natural weeks between two dates based on week of year
public static int weeksBetween(ReadablePartial date1, ReadablePartial date2) {
int comp = date1.compareTo(date2);
if (comp == 0) {
return 0;
}
if (comp > 0) {
ReadablePartial mid = date2;
date2 = date1;
date1 = mid;
}
int year1 = date1.get(DateTimeFieldType.weekyear());
int year2 = date2.get(DateTimeFieldType.weekyear());
if (year1 == year2) {
return date2.get(DateTimeFieldType.weekOfWeekyear()) - date1.get(DateTimeFieldType.weekOfWeekyear());
}
int weeks1 = 0;
LocalDate lastDay1 = new LocalDate(date1.get(DateTimeFieldType.year()), 12, 31);
if (lastDay1.getWeekyear() > year1) {
lastDay1 = lastDay1.minusDays(7);
weeks1++;
}
weeks1 += lastDay1.getWeekOfWeekyear() - date1.get(DateTimeFieldType.weekOfWeekyear());
int midWeeks = 0;
for (int i = year1 + 1; i < year2; i++) {
LocalDate y1 = new LocalDate(i, 1, 1);
int yearY1 = y1.getWeekyear();
if (yearY1 < i) {
y1 = y1.plusDays(7);
midWeeks++;
}
LocalDate y2 = new LocalDate(i, 12, 31);
int yearY2 = y2.getWeekyear();
if (yearY2 > i) {
y2 = y2.minusDays(7);
midWeeks++;
}
midWeeks += y2.getWeekOfWeekyear() - y1.getWeekOfWeekyear();
}
int weeks2 = 0;
LocalDate firstDay2 = new LocalDate(date2.get(DateTimeFieldType.year()), 1, 1);
if (firstDay2.getWeekyear() < firstDay2.getYear()) {
firstDay2 = firstDay2.plusDays(7);
weeks2++;
}
weeks2 += date2.get(DateTimeFieldType.weekOfWeekyear()) - firstDay2.getWeekOfWeekyear();
return weeks1 + midWeeks + weeks2;
}
int startWeek = c1.get(Calendar.WEEK_OF_YEAR);
int endWeek = c2.get(Calendar.WEEK_OF_YEAR);
int diff = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
int deltaYears = 0;
for(int i = 0;i < diff;i++){
deltaYears += c1.getWeeksInWeekYear();
c1.add(Calendar.YEAR, 1);
}
diff = (endWeek + deltaYears) - startWeek;
Includes the year differences.
This worked for me :)
private int weeksBetween(Calendar startDate, Calendar endDate) {
startDate.set(Calendar.HOUR_OF_DAY, 0);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
int start = (int)TimeUnit.MILLISECONDS.toDays(
startDate.getTimeInMillis())
- startDate.get(Calendar.DAY_OF_WEEK);
int end = (int)TimeUnit.MILLISECONDS.toDays(
endDate.getTimeInMillis());
return (end - start) / 7;
}
if this method returns 0 they are in the same week
if this method return 1 endDate is the week after startDate
if this method returns -1 endDate is the week before startDate
you get the idea
Without using JodaTime, I was able to accurately calculate the number of weeks between 2 calendars (which accounts for leap years etc.)
private fun calculateNumberOfWeeks() {
val calendarFrom = Calendar.getInstance()
calendarFrom.set(Calendar.HOUR_OF_DAY, 0)
calendarFrom.set(Calendar.MINUTE, 0)
calendarFrom.set(Calendar.SECOND, 0)
calendarFrom.set(Calendar.MILLISECOND, 0)
val calendarTo = Calendar.getInstance()
calendarTo.add(Calendar.MONTH, months)
calendarTo.set(Calendar.HOUR_OF_DAY, 0)
calendarTo.set(Calendar.MINUTE, 0)
calendarTo.set(Calendar.SECOND, 0)
calendarTo.set(Calendar.MILLISECOND, 0)
var weeks = -1
while (calendarFrom.timeInMillis < calendarTo.timeInMillis) {
calendarFrom.add(Calendar.DATE, 7)
weeks++
Log.d(Constants.LOG_TAG, "weeks $weeks")
}
}
Easy way
Calendar cal1 = new GregorianCalendar();
Calendar cal2 = new GregorianCalendar();
cal1.set(2014, 3, 3);
cal2.set(2015, 3, 6);
weekscount.setText("weeks= "+ ( (cal2.getTime().getTime() - cal1.getTime().getTime()) / (1000 * 60 * 60 * 24))/7);
Here is a simple way to find the number of weeks between two dates.
SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy");
String classStartData = "31 01 2021";
String classEndData = "08 03 2021";
Date dateClassStart = myFormat.parse(classStartData);
Date dateClassEnd = myFormat.parse(classEndData);
long differenceWeek = dateClassEnd.getTime() - dateClassStart.getTime();
int programLength = (int)(TimeUnit.DAYS.convert(differenceWeek, TimeUnit.MILLISECONDS)/7);
System.out.println("Class length in weeks: " +programLength);
After referring many solution, this worked for me.
{Provided I did not want to use external Libraries}
public static int getNumberOfWeeks(Date date1, Date date2) {
if (date1.after(date2)) {
return getNumberOfWeeks(date2, date1);
}
Date date = date1;
int days = 0;
while (date.before(date2)) {
days++;
date = addDays(date, 1);
}
return days/7;
}
To add days to a date :
Date addDays(Date date, int days) {
if (days == 0) {
return date;
} else {
Date shiftedDate = new Date(date.getTime() + (long)days * 86400000L);
return shiftedDate;
}
}
Take a look at the following article: Java - calculate the difference between two dates
The daysBetween method will allow you to get the number of days between dates. Then you can simply divide by 7 to get the number of full weeks.
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);
int week = (dayCount / 7) ;
Hope this might Help you
public int diffInWeeks(Date start, Date end) {
long diffSeconds = (end.getTime() - start.getTime())/1000;
return (int)diffSeconds/(60 * 60 * 24 * 7);
}