How can you calculate the number of weeks between two dates in Android? I have done something like this
int week1 = calendar1.get(Calendar.WEEK_OF_YEAR);
int week2 = calendar2.get(Calendar.WEEK_OF_YEAR);
int calendarWeekDifference = week2 - week1;
However this does not work when the two dates are in different years. How can I achieve a solution so that it will work across different years?
EDIT
I have tried doing the following with Joda-Time:
public static int weeksTouched(Calendar fromDate, Calendar toDate){
DateTime fromDateTime = new DateTime(fromDate);
DateTime toDateTime = new DateTime(toDate);
DateTime epoch = new DateTime(0);
Weeks fromWeeks = Weeks.weeksBetween(epoch, fromDateTime);
Weeks toWeeks = Weeks.weeksBetween(epoch, toDateTime);
int betweenWeeks = toWeeks.getWeeks() - fromWeeks.getWeeks();
return betweenWeeks;
}
This almost works but for some reason it thinks the start of a week is Thursday. I want the start of a week to be Monday so that a Monday to the next Saturday would return 0 (same week) but a Saturday to the next day Sunday would return 1 (different weeks).
public int getWeekDifference(long fromDateInMills, long toDateInMills) {
int weeks = Weeks.weeksBetween(new DateTime(fromDateInMills), new DateTime(toDateInMills)).getWeeks();
// when we select any future date than week difference comes in negative so
// just interchange millisecond You will get week difference in positive
if (weeks < 0) {
weeks = Weeks.weeksBetween(new DateTime(toDateInMills), new DateTime(fromDateInMills)).getWeeks();
}
return weeks;
}
Some answers here give wrong results, and some require an extra library. I managed to come up with a method that calculates the week-diff using standard Calendar APIs.
It correctly handles edge cases like 2000-01-01 to 2000-12-31 (54 weeks implies a difference of 53).
getWeeksBetween() using Calendar API
public static int getWeeksBetween(final Date start, final Date end) {
final Calendar c1 = Calendar.getInstance(Locale.US);
final Calendar c2 = Calendar.getInstance(Locale.US);
// Skip time part! Not sure if this is needed, but I wanted clean dates.
CalendarUtils.setDateWithNoTime(c1, start);
CalendarUtils.setDateWithNoTime(c2, end);
CalendarUtils.goToFirstDayOfWeek(c1);
CalendarUtils.goToFirstDayOfWeek(c2);
int weeks = 0;
while (c1.compareTo(c2) < 0) {
c1.add(Calendar.WEEK_OF_YEAR, 1);
weeks++;
}
return weeks;
}
And some helper methods:
public static int goToFirstDayOfWeek(final Calendar calendar) {
final int firstDayOfWeek = calendar.getFirstDayOfWeek();
calendar.set(Calendar.DAY_OF_WEEK, firstDayOfWeek);
return firstDayOfWeek;
}
public static void setDateWithNoTime(final Calendar calendar, final Date date) {
calendar.setTime(date);
clearTime(calendar);
}
public static void clearTime(final Calendar calendar) {
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
Without using JodaTime, I came up with this solution to calculate number of weeks:
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")
}
}
I would recommend that instead of calculating the difference in weeks you should try to find the difference in days and the result you can divide by 7.
So it would be weeks = (daysBetweenDates / 7)
using java 8
public void weeks_between_two_dates_in_java_with_java8 () {
LocalDate startDate = LocalDate.of(2005, Month.JANUARY, 1);
LocalDate endDate = LocalDate.of(2006, Month.JANUARY, 1);
long weeksInYear = ChronoUnit.WEEKS.between(startDate, endDate);
}
or using joda time api
public void weeks_between_two_dates_in_java_with_joda () {
DateTime start = new DateTime(2005, 1, 1, 0, 0, 0, 0);
DateTime end = new DateTime(2006, 1, 1, 0, 0, 0, 0);
Weeks weeks = Weeks.weeksBetween(start, end);
int weeksInYear = weeks.getWeeks();
}
What about a sort of low tech solution just using maths?
You have the Week_OF_YEAR from each date. Also the the YEAR number for each.
Multiply each Year number by 52, add that to the WEEK_OF_YEAR then subtract the two numbers.
for example....
2018 Week 50
to
2019 Week 2
2018*52 = 104936 + 50 weeks = 104986
2019*52 = 104988 + 2 weeks = 104990
104990 - 104986 = 4 weeks
Another alternative solution. My basic concept is:
Trim given dates to the respective Mondays 00:00:00.000
Calculate milliseconds between those trimmed dates and then divide it by milliseconds of a week.
A sample in Java:
public class Main {
public static void main(String[] args) {
Calendar Monday = Calendar.getInstance();
Monday.set(2020, 11, 28, 12, 34, 56); // 2020-12-28T12:34:56
Calendar Saturday = Calendar.getInstance();
Saturday.set(2021, 0, 2, 21, 43, 57); // 2021-01-02T21:43:57
Calendar Sunday = Calendar.getInstance();
Sunday.set(2021, 0, 3, 0, 1, 2); // 2021-01-03T00:01:02
Calendar NextMonday = Calendar.getInstance();
NextMonday.set(2021, 0, 4, 1, 23, 45); // 2021-01-04T01:23:45
System.out.println(String.format(": %d week(s)", weeksTouched(Monday, Sunday)));
System.out.println(String.format(": %d week(s)", weeksTouched(Saturday, Sunday)));
System.out.println(String.format(": %d week(s)", weeksTouched(Sunday, NextMonday)));
}
public static int weeksTouched(Calendar fromDate, Calendar toDate){
System.out.print(String.format("%s -> %s", fromDate.getTime(), toDate.getTime()));
return (int) (
(trimToMonday(toDate).getTimeInMillis() - trimToMonday(fromDate).getTimeInMillis())
/ (1000 * 60 * 60 * 24 * 7)
);
}
private static Calendar trimToMonday(Calendar input) {
Calendar output = (Calendar) input.clone();
switch (output.get(Calendar.DAY_OF_WEEK)) {
case Calendar.TUESDAY:
output.add(Calendar.DAY_OF_MONTH, -1);
break;
case Calendar.WEDNESDAY:
output.add(Calendar.DAY_OF_MONTH, -2);
break;
case Calendar.THURSDAY:
output.add(Calendar.DAY_OF_MONTH, -3);
break;
case Calendar.FRIDAY:
output.add(Calendar.DAY_OF_MONTH, -4);
break;
case Calendar.SATURDAY:
output.add(Calendar.DAY_OF_MONTH, -5);
break;
case Calendar.SUNDAY:
output.add(Calendar.DAY_OF_MONTH, -6);
break;
}
output.set(Calendar.HOUR_OF_DAY, 0);
output.set(Calendar.MINUTE, 0);
output.set(Calendar.SECOND, 0);
output.set(Calendar.MILLISECOND, 0);
return output;
}
}
Output:
Mon Dec 28 12:34:56 JST 2020 -> Sun Jan 03 00:01:02 JST 2021: 0 week(s)
Sat Jan 02 21:43:57 JST 2021 -> Sun Jan 03 00:01:02 JST 2021: 0 week(s)
Sun Jan 03 00:01:02 JST 2021 -> Mon Jan 04 01:23:45 JST 2021: 1 week(s)
This will give you number of weeks b/w two dates.
public void getNoOfWeek()
{
Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();
date1.clear();
date1.set(2015, 12, 29); // set date 1 (yyyy,mm,dd)
date2.clear();
date2.set(2016, 02, 7); //set date 2 (yyyy,mm,dd)
long diff = date2.getTimeInMillis() - date1.getTimeInMillis();
float dayCount = (float) diff / (24 * 60 * 60 * 1000);
int week = (int) (dayCount / 7);
System.out.println(week);
}
Related
I need to claculate the number of days between two dates without using any date or calendar classes provided by any library.
Here's my idea:
numberOfDays = Math.abs((toYear - fromYear) * 365);
numberOfDays = numberOfDays + Math.abs((toMonth - fromMonth) * 12);
numberOfDays = numberOfDays + Math.abs((toDay - fromDay));
Thoughts?
How many days between the start date and the end of the month?
How many days in each full month until the end of the year?
How many days in each full year until the year of the end date (counting leap years)?
How many days in each full month until the last month?
How many days from the start of the last month until the end date?
Some of these numbers may be zero.
In Java 8 you can do the following:
long days = ChronoUnit.DAYS.between(LocalDate.of(2014, Month.MARCH, 01), LocalDate.of(2014, Month.FEBRUARY, 15));
Would something like this do?
//get 2 random dates
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = new Date();
Date date2 = sdf.parse("2014-9-12");
final long msInADay = 24*60*60*1000; //turn a day to ms
//divide time difference by the ms of a day
int difference = (int)((date2.getTime() - date1.getTime()) / msInADay);
System.out.println(Math.abs(difference));//Math.abs so you can subtract dates in any order.
EDIT after updating your question:
You can do this:
static int calcDayDiff(int startY, int startM, int startD, int endY, int endM, int endD){
int result = (startY - endY) * 365;
result += (startM - endM) * 31;
result += (startD - endD);
return Math.abs(result);
}
Testing with: System.out.println(calcDayDiff(2014,9,13,2013,8,12)); will print 397
Note though that this is not a very good solution since not every month contains 31 days and not every year 365. You can fix the month day difference by adding some simple logic inside the method to not always multiply by 31. Since it's an assignment i guess you will be ok to consider every year having 365 days.
public class test {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.set(2014, 8, 1, 0, 0, 0);
Date s = cal.getTime();
Date e = new Date();
System.out.println(days(s,e));
}
public static int days(Date start, Date end){
double aTms = Math.floor(start.getTime() - end.getTime());
return (int) (aTms/(24*60*+60*1000));
}
}
This is homework.
I am trying to find every occurrence of a Sunday landing on the first of a month between Jan 1 1900 (which we are assuming was a Monday) and Dec 31 of a year that the user inputs. The calendar extension is off-limits.
I am returning dates in the correct format, but they do not match up with the example code our instructor provided.
In the given example, an input of 1902 should return:
1 Apr 1900
1 Jul 1900
1 Sep 1901
1 Dec 1901
1 Jun 1902
For 1902, my code returns:
1 Mar 1900
1 Jan 1901
1 Apr 1901
1 May 1901
1 Feb 1902
1 Jun 1902
1 Jul 1902
import java.util.Scanner;
public class Sundays {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.print("Enter the ending year: ");
int userInputYear = reader.nextInt();
int[] orderedLengthOfMonthsArray = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
String[] orderedNamesOfMonthsArray = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int month = 0;
int dayOfWeek = 1; // initialized to MONDAY Jan 1, 1900 -- Sunday would be #7
int dayOfMonth = 1;
for (int year = 1900; year <= userInputYear; year++) {
for (month = 0; month < orderedLengthOfMonthsArray.length; month++) {
for (dayOfMonth = 1; dayOfMonth <= orderedLengthOfMonthsArray[month]; dayOfMonth++) {
dayOfWeek++;
if (dayOfMonth == 1 && dayOfWeek == 7) {
System.out.println(dayOfMonth + " " + orderedNamesOfMonthsArray[month] + " " + year);
}
if (dayOfWeek == 8) {
dayOfWeek = 1;
}
}
}
}
}
}
Swap the if statement and the increase of dayOfWeek.
for (dayOfMonth = 1; dayOfMonth <= orderedLengthOfMonthsArray[month]; dayOfMonth++) {
if (dayOfMonth == 1 && dayOfWeek == 7) {
System.out.println(dayOfMonth + " " + orderedNamesOfMonthsArray[month] + " " + year);
}
dayOfWeek++;
if (dayOfWeek == 8) {
dayOfWeek = 1;
}
}
When you are in the dayOfMonth for loop, you already have the correct day of the week (initially Monday, Jan 1st, 1900), so if you first increase it, then the check afterwards would be incorrect.
if (dayOfWeek == 7) {
dayOfWeek = 1;
}
So your week has 6 days? I think you should either reset to zero or reset when dayOfWeek is 8.
Someone mentioned Joda-Time magic… So here's my solution using Joda-Time 2.3.
While the question (a homework assignment) forbade the use of added libraries…
The comparison may be enlightening.
The student should soon learn that the java.util.Date & Calendar classes are notoriously troublesome and should be avoided for real-world work. They are supplanted in Java 8 by the new java.time.* package which is inspired by Joda-Time and defined by JSR 310.
My example code uses LocalDate which should only be used if your are absolutely certain that you don't care about (a) time of day, and (b) time zones. I do not usually recommend this approach as naïve programmers who believe they need neither time nor zone often turn out to be mistaken.
// Start
LocalDate start = new LocalDate( 1900, 1, 1 );
// Stop
// Using "half-open" comparison. We care about December 31 of specified year, but we will test for January 1 of year after.
String input = "1930";
int year = Integer.valueOf( input );
year = ( year + 1 ); // Add one to get to next year, for "half-open" approach.
LocalDate stop = new LocalDate( year, 1, 1 );
// Collect each LocalDate where the first of the month is a Sunday.
java.util.List<LocalDate> localDates = new java.util.ArrayList<LocalDate>();
LocalDate localDate = start;
do {
if ( localDate.getDayOfWeek() == DateTimeConstants.SUNDAY ) { // Comparing 'int' primitive values.
localDates.add( localDate ); // Collect this LocalDate instance.
}
localDate = localDate.plusMonths( 1 ); // Move on to next month. Joda-Time is smart about various month-ends and leap-year.
} while ( localDate.isBefore( stop ) ); // "Half-Open" means test "<" rather than "<=".
Dump to console…
System.out.println( "The First-Of-The-Month days that are Sundays from " + start + " (inclusive) to " + stop + " (exclusive):" );
System.out.println( localDates );
The First-Of-The-Month days that are Sundays from 1900-01-01 (inclusive) to 1931-01-01 (exclusive):
[1900-04-01, 1900-07-01, 1901-09-01, 1901-12-01, 1902-06-01, 1903-02-01, 1903-03-01, 1903-11-01, 1904-05-01, 1905-01-01, 1905-10-01, 1906-04-01, 1906-07-01, 1907-09-01, 1907-12-01, 1908-03-01, 1908-11-01, 1909-08-01, 1910-05-01, 1911-01-01, 1911-10-01, 1912-09-01, 1912-12-01, 1913-06-01, 1914-02-01, 1914-03-01, 1914-11-01, 1915-08-01, 1916-10-01, 1917-04-01, 1917-07-01, 1918-09-01, 1918-12-01, 1919-06-01, 1920-02-01, 1920-08-01, 1921-05-01, 1922-01-01, 1922-10-01, 1923-04-01, 1923-07-01, 1924-06-01, 1925-02-01, 1925-03-01, 1925-11-01, 1926-08-01, 1927-05-01, 1928-01-01, 1928-04-01, 1928-07-01, 1929-09-01, 1929-12-01, 1930-06-01]
Just for fun, while you have explicitly mentioned not to use Calendar, here is how we could do it:
public static List<Date> mondaysFirst(int firstYear, int lastYear) {
final List<Date> dates = new ArrayList<>();
final Calendar c1 = Calendar.getInstance(Locale.US);
c1.set(firstYear, 0, 1, 0, 0, 0);
final Calendar c2 = Calendar.getInstance(Locale.US);
c2.set(lastYear, 11, 31, 23, 59, 59);
while (c1.before(c2)) {
final int dayOfTheWeek = c1.get(Calendar.DAY_OF_WEEK);
// is sunday
if (dayOfTheWeek == 1) {
dates.add(c1.getTime());
}
c1.add(Calendar.MONTH, 1);
}
return dates;
}
And to print the results:
final List<Date> dates = mondaysFirst(1900, 1902);
final SimpleDateFormat sf = new SimpleDateFormat("dd MMM yyyy");
for (Date date: dates) {
System.out.println(sf.format(date));
}
Working Example.
I'm sure that there is some Joda-Time magic to make this even shorter.
I'm trying to come up with a way to calculate the number of days between two different dates, however there will be certain days of the week that are only to be accounted for. For example, let's say we want to calculate the number of work days between 8/1 and 8/31, but employee only works Monday, Tuesday and Wednesday. The result would be that this employee only works 15 days during that period.
Has anyone put together something similar using the java Calendar class?
Try Joda Time, is the best solution to manage Date and Time.
The code of dogbane corrected:
final Calendar current = Calendar.getInstance();
current.set(2011, 7, 1);
final Calendar end = Calendar.getInstance();
end.set(2011, 7, 31);
int count = 0;
while (!current.after(end)) {
int dayOfWeek = current.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek == Calendar.MONDAY ||
dayOfWeek == Calendar.TUESDAY ||
dayOfWeek == Calendar.WEDNESDAY) {
count++;
}
current.add(Calendar.DAY_OF_MONTH, 1);
}
System.out.println(count);
If use Joda Time:
DateTime current = new DateTime(2011, 8, 1, 0, 0, 0, 0);
DateTime end = new DateTime(2011, 8, 31, 0, 0, 0, 0);
int count = 0;
while (!current.isAfter(end)) {
int dayOfWeek = current.getDayOfWeek();
if (dayOfWeek == DateTimeConstants.MONDAY || dayOfWeek == DateTimeConstants.TUESDAY
|| dayOfWeek == DateTimeConstants.WEDNESDAY) {
count++;
}
current = current.plusDays(1);
}
System.out.println(count);
You can do this by incrementing the date by one day until you reach the end date. At each iteration, check if the day is Mon, Tue or Wed and increment a counter.
For example:
final Calendar current = Calendar.getInstance();
current.set(2011, 7, 1);
final Calendar end = Calendar.getInstance();
end.set(2011, 7, 31);
int count = 0;
while (current.compareTo(end) != 0) {
current.add(Calendar.DAY_OF_MONTH, 1);
int dayOfWeek = current.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek == Calendar.MONDAY ||
dayOfWeek == Calendar.TUESDAY ||
dayOfWeek == Calendar.WEDNESDAY) {
count++;
}
}
System.out.println(count);
You could roll your own solution with java.util.Calendar; however, I suggest looking at some existing library, such as ObjectLab Kit date utilities.
I need to be able to calculate the "Friday before" today in Java or Groovy.
For example, if today is Monday, February 21, the "Friday before" would be Friday, February 18.
And if today was Tuesday, February 1, the "Friday before" would be Friday, January 28.
What would be the best way to do this? What existing classes can I most effectively leverage?
You can use a loop:
Calendar c = Calendar.getInstance();
while(c.get(Calendar.DAY_OF_WEEK) != Calendar.FRIDAY)
{
c.add(Calendar.DAY_OF_WEEK, -1)
}
Or
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_WEEK, -((c.get(Calendar.DAY_OF_WEEK) + 1) % 7));
I would make a method that gave me the number of days that have passed since the given day.
// Uses now by default
public static int daysSince(int day) {
return daysSince(day, Calendar.getInstance());
}
// Gives you the number of days since the given day of the week from the given day.
public static int daysSince(int day, Calendar now) {
int today = now.get(Calendar.DAY_OF_WEEK);
int difference = today - day;
if(difference <= 0) difference += 7;
return difference;
}
// Simple use example
public static void callingMethod() {
int daysPassed = daysSince(Calendar.FRIDAY);
Calendar lastFriday = Calendar.getInstance().add(Calendar.DAY_OF_WEEK, -daysPassed);
}
How do I convert a 7-digit julian date into a format like MM/dd/yyy?
Found a useful site: http://www.rgagnon.com/javadetails/java-0506.html
This should do the trick:
public static int[] fromJulian(double injulian) {
int jalpha,ja,jb,jc,jd,je,year,month,day;
double julian = julian + HALFSECOND / 86400.0;
ja = (int) julian;
if (ja>= JGREG) {
jalpha = (int) (((ja - 1867216) - 0.25) / 36524.25);
ja = ja + 1 + jalpha - jalpha / 4;
}
jb = ja + 1524;
jc = (int) (6680.0 + ((jb - 2439870) - 122.1) / 365.25);
jd = 365 * jc + jc / 4;
je = (int) ((jb - jd) / 30.6001);
day = jb - jd - (int) (30.6001 * je);
month = je - 1;
if (month > 12) month = month - 12;
year = jc - 4715;
if (month > 2) year--;
if (year <= 0) year--;
return new int[] {year, month, day};
}
Starting with Java 8, this becomes a one-liner to get the LocalDate:
LocalDate.MIN.with(JulianFields.JULIAN_DAY, julianDay)
.format(DateTimeFormatter.ofPattern("MM/dd/yyyy"));
Where julianDay is your 7-digit number.
simple way is here and this will return approx 100% accurate information.
String getDobInfo(double doubleString){
SweDate sweDate = new SweDate(doubleString);
int year = sweDate.getYear();
int month = sweDate.getMonth();
int day = sweDate.getDay();
// getting hour,minute and sec from julian date
int hour = (int) Math.floor(sweDate.getHour());
int min = (int) Math
.round((sweDate.getHour() - Math.floor(hour)) * 60.0);
int sec = (int) (((sweDate.getHour() - Math.floor(hour)) * 60.0 - Math
.floor(min)) * 60.0);
return "DOB:(DD:MM:YY) "+day+":"+month+":"+year+" TOB:(HH:MM:SS) "+hour+":"+min+":"+sec;
}
download the Swiss Ephemeris library and enjoy coding!!!
Do you really mean a Julian date, like astronomers use? Ordinal dates, which are specified as a year (four digits) and the day within that year (3 digits), are sometimes incorrectly called Julian dates.
static String formatOrdinal(int year, int day) {
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.DAY_OF_YEAR, day);
Date date = cal.getTime();
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
return formatter.format(date);
}
This will give you the date at 00:00 local time; you may want to set the timezone on the calendars to GMT instead, depending on the application.
I see there are enough answers already provided. But any calendar related question is only half answered without mentioning joda-time ;-). Here is how simple it is with this library
// setup date object for the Battle of Hastings in 1066
Chronology chrono = JulianChronology.getInstance();
DateTime dt = new DateTime(1066, 10, 14, 10, 0, 0, 0, chrono);