How to calculate the number of Tuesday in one month? - java

How to calculate number of Tuesday in one month?
Using calender.set we can set particular month, after that how to calculate number of Mondays, Tuesdays etc. in that month?
Code is :
public static void main(String[] args )
{
Calendar calendar = Calendar.getInstance();
int month = calendar.MAY;
int year = 2012;
int date = 1 ;
calendar.set(year, month, date);
int MaxDay = calendar.getActualMaximum(calendar.DAY_OF_MONTH);
int mon=0;
for(int i = 1 ; i < MaxDay ; i++)
{
calendar.set(Calendar.DAY_OF_MONTH, i);
if (calendar.get(Calendar.DAY_OF_WEEK) == calendar.MONDAY )
mon++;
}
System.out.println("days : " + MaxDay);
System.out.println("MOndays :" + mon);
}

Without writing whole code here is the general idea:
Calendar c = Calendar.getInstance();
c.set(Calendar.MONTH, Calendar.MAY); // may is just an example
c.set(Calendar.YEAR, 2012);
int th = 0;
int maxDayInMonth = c.getMaximum(Calendar.MONTH);
for (int d = 1; d <= maxDayInMonth; d++) {
c.set(Calendar.DAY_OF_MONTH, d);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
if (Calendar.THURSDAY == dayOfWeek) {
th++;
}
}
This code should count number of Thursday. I believe you can modify it to count number of all days of week.
Obviously this code is not efficient. It iterates over all the days in the month. You can optimize it by getting just get day of the week of the first day, the number of days in month and (I believe) you can write code that calculates number of each day of week without iterating over the whole month.

With Java 8+, you could write it in a more concise way:
public static int countDayOccurenceInMonth(DayOfWeek dow, YearMonth month) {
LocalDate start = month.atDay(1).with(TemporalAdjusters.nextOrSame(dow));
return (int) ChronoUnit.WEEKS.between(start, month.atEndOfMonth()) + 1;
}
Which you can call with:
int count = countDayOccurenceInMonth(DayOfWeek.TUESDAY, YearMonth.of(2012, 1));
System.out.println(count); //prints 5

AlexR mentioned the more efficient version. Thought I would give it a whirl:
private int getNumThursdays() {
// create instance of Gregorian calendar
Calendar gc = new GregorianCalendar(TimeZone.getTimeZone("EST"), Locale.US);
int currentWeekday = gc.get(Calendar.DAY_OF_WEEK);
// get number of days left in month
int daysLeft = gc.getActualMaximum(Calendar.DAY_OF_MONTH) -
gc.get(Calendar.DAY_OF_MONTH);
// move to closest thursday (either today or ahead)
while(currentWeekday != Calendar.THURSDAY) {
if (currentWeekday < 7) currentWeekday++;
else currentWeekday = 1;
daysLeft--;
}
// calculate the number of Thursdays left
return daysLeft / 7 + 1;
}
note: When getting the current year, month, day etc. it is dependent on your environment. For example if someone manually set the time on their phone to something wrong, then this calculation could be wrong. To ensure correctness, it is best to pull data about the current month, year, day, time from a trusted source.

Java calendar actually has a built in property for that Calendar.DAY_OF_WEEK_IN_MONTH
Calendar calendar = Calendar.getInstance(); //get instance
calendar.set(Calendar.DAY_OF_WEEK, 3); //make it be a Tuesday (crucial)
//optionally set the month you want here
calendar.set(Calendar.MONTH, 4) //May
calendar.getActualMaximum(Calendar.DAY_OF_WEEK_IN_MONTH); //for this month (what you want)
calendar.getMaximum(Calendar.DAY_OF_WEEK_IN_MONTH); //for any month (not so useful)

Related

Java - Count day of month occurrences in an interval of time

I am using Java 8, i need to count how many days we have in an interval having index = x. Example: from 1-1-2019 till 31-1-2019 we have 1 occurrence of Day 1.
I do not want the range of days, just the count of day X
If its the last day of month, i want to count them all example: 30 +30 +31+28
try this method:
public static int getDateCount(LocalDate startDate, LocalDate endDate, final int index) {
long numOfDaysBetween = ChronoUnit.DAYS.between(startDate, endDate);
return IntStream.iterate(0, i -> i + 1)
.limit(numOfDaysBetween)
.mapToObj(i -> startDate.plusDays(i))
.filter(i -> i.getDayOfMonth() == index)
.collect(Collectors.toList()).size();
}
usage:
public static void main(String[] args){
LocalDate startDate = LocalDate.of(2019,1,1);
LocalDate endDate = LocalDate.of(2019,1,31);
int index=1;
System.out.println(getDateCount(startDate,endDate,index));
}
output:
1
Here i first calculated days between two dates then extracted all days occuring between these dates then filtered them to desired day e.g 1 in that case.
Note : that might not be the best and effective solution
I don't know if the java.time API provides methods to directly do this, but you can always loop through all the dates between the start and end check them one by one.
LocalDate start = LocalDate.of(2019, 1, 1);
LocalDate end = LocalDate.of(2022, 12, 31);
long daysBetween = ChronoUnit.DAYS.between(start, end);
System.out.println(daysBetween);
// you might want to use a parallel stream. It might speed things up a little
long count = LongStream.range(0, daysBetween + 1)
.mapToObj(start::plusDays)
.filter(x -> x.getDayOfMonth() == index)
.count();
System.out.println(count);
There is a special case for the last day of the month, you need:
.filter(x -> x.equals(x.with(TemporalAdjusters.lastDayOfMonth())))
here is the solution:
LocalDate start = LocalDate.of(2019, 1, 1);
LocalDate end = LocalDate.of(2019, 3, 31);
long daysBetween = ChronoUnit.DAYS.between(start, end);
int index = 1;
int count = 0;
start = start.minusDays(1);
for(int i = 0; i <= daysBetween; i++){
start = start.plusDays(1);
if (start.getDayOfMonth() == index) {
count++;
}
}
System.out.println(count);
finding days in-between using:
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();
finding specific day was there or not, suppose 11th of month.
(startDay + days) contains the day you require something like that.
public long getNumberOfDayOfMonthBetweenDates(LocalDate startDate, LocalDate endDate, int dayOfMonth) {
long result = -1;
if (startDate != null && endDate != null && dayOfMonth > 0 && dayOfMonth < 32) {
result = 0;
LocalDate startDay = getDayInCurrentMonth(startDate, dayOfMonth);
// add one day as end date is exclusive
// add + 1 to cover higher possibilities (month and a half or half month or so)
long totalMonths = ChronoUnit.MONTHS.between(startDate, endDate.plusDays(1)) + 2;
for (int i = 0; i < totalMonths; i++) {
if ((!startDay.isBefore(startDate) && startDay.isBefore(endDate)) || startDay.equals(startDate) || startDay.equals(endDate)) {
result++;
}
startDay = getDayInCurrentMonth(startDay.plusMonths(1), dayOfMonth);
}
}
return result;
}
private LocalDate getDayInCurrentMonth(LocalDate startDate, int dayOfMonth) {
LocalDate dayOfThisMonth;
try {
dayOfThisMonth = startDate.withDayOfMonth(dayOfMonth);
} catch (DateTimeException e) {
// handle cases where current month does not contain the given day (example 30 in Feb)
dayOfThisMonth = startDate.withDayOfMonth(startDate.lengthOfMonth());
}
return dayOfThisMonth;
}

Java: How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

I am new to programming and java and I am trying to solve the following problem:
How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
Here is my code:
int count, sum = 0;
for (int i = 1901; i < 2001; i++) {
LocalDate test = LocalDate.of(i, 1, 1);
sum += test.lengthOfYear();
}
for (int i = 1; i < sum; i++) {
LocalDate date1 = LocalDate.of(1901, 1, 1);
date1 = date1.plusDays(i);
if (date1.getMonth() == JANUARY && date1.getDayOfWeek() == SUNDAY) {
count++;
}
}
System.out.println(count);
If I print the results, it seems to be working fine.
My result is 443, but the correct answer is 171. What am I doing wrong?
Thank you!
I suspect 443 is the total number of Sundays in January in the twentieth century. This happens because you walk over all possible days of the twentieth century and then check if the current month is January and if the current day is Sunday.
This is not what you want.
I would use a different approach:
Walk over the 1st day of each month of each year.
And then check if it's a Sunday.
The code will probably be much faster.
// Each year
for (int y = 1901; y < 2001; y++) {
// Each month of the year
for (int m = 1; m <= 12; m++) {
if (LocalDate.of(y, m, 1).getDayOfWeek() == DayOfWeek.SUNDAY) {
count++;
}
}
}
Your code would have been correct if you changed date1.getMonth() == JANUARY to date1.getDayOfMonth() == 1. However, the method is very inefficient, because it checks each day of the twentieth century, while it only needs to check the first day of each month. The abovementioned code is approximately 40 times faster on my machine.
Here is an equivalent of the abovementioned code, with functional style:
long count = Stream.iterate(YearMonth.of(1901, 1), ym -> ym.plusMonths(1))
.takeWhile(ym -> ym.isBefore(YearMonth.of(2001, 1)))
.map(ym -> ym.atDay(1).getDayOfWeek())
.filter(DayOfWeek.SUNDAY::equals)
.count();
Using Todd's Java-TimeStream, with functional style:
YearMonthStream
.from(YearMonth.of(1901, 1))
.until(YearMonth.of(2000, 12))
.stream()
.map(ym -> ym.atDay(1).getDayOfWeek())
.filter(DayOfWeek.SUNDAY::equals)
.count();
I see some mistakes:
public static void main(String[] args) {
int count, sum = 0;
for (int i = 1901; i < 2001; i++) { // There is a mistake here, I dont know what you want to compute in this loop!
LocalDate test = LocalDate.of(i,1,1);
sum += test.lengthOfYear();
}
for (int i = 1; i < sum; i++) {
LocalDate date1 = LocalDate.of(1901,1,1); // There is a mistake here, date1 must be outside of this loop
date1 = date1.plusDays(i); // There is a mistake here, plusDays why??
if(date1.getMonth() == JANUARY && date1.getDayOfWeek() == SUNDAY) { // There is a mistake here, why are you cheking this: date1.getMonth() == JANUARY ?
count++;
}
}
System.out.println(count);
}
A simple solution:
public static void main(String[] args) {
int count = 0;
LocalDate date1 = LocalDate.of(1901, Month.JANUARY, 1);
LocalDate endDate = LocalDate.of(2001, Month.JANUARY, 1);
while (date1.isBefore(endDate)) {
date1 = date1.plusMonths(1);
if (date1.getDayOfWeek() == DayOfWeek.SUNDAY) {
count++;
}
}
System.out.println(count);
}
Apart from the error that has already been flagged, you could reconsider your design and use the YearMonth class which seems better suited to your use case than LocalDate:
public static void main(String[] args) {
YearMonth start = YearMonth.of(1901, 1);
YearMonth end = YearMonth.of(2000, 12);
int count = 0;
for (YearMonth ym = start; !ym.isAfter(end); ym = ym.plusMonths(1)) {
//is first day of month a sunday?
if (ym.atDay(1).getDayOfWeek() == SUNDAY) count ++;
}
System.out.println(count); //171
}
You start by finding the number of days in the period you're checking, and then start a for loop to run through that period. So far so good. But your condition for incrementing the count is wrong:
if(date1.getMonth() == JANUARY && date1.getDayOfWeek() == SUNDAY)
This means that as you loop over each day, you increase count if that date is a Sunday in January. You don't check whether that Sunday was the first of January, and you don't count anything from February to December.
You should be checking that it's the first day of the month and Sunday, not the first month of the year and Sunday.
The following code should output the correct value.
public static void main(String[] args) {
int count = 0, sum = 0;
for (int i = 1901; i < 2001; i++) {
LocalDate test = LocalDate.of(i, 1, 1);
sum += test.lengthOfYear();
}
for (int i = 1; i < sum; i++) {
LocalDate date1 = LocalDate.of(1901, 1, 1);
date1 = date1.plusDays(i);
if (date1.getDayOfMonth() == 1 && date1.getDayOfWeek() == java.time.DayOfWeek.SUNDAY) {
count++;
}
}
System.out.println(count);
}
Note that:
You don't need to check that month is January, because your requirement is about any 1st of the month.
You must also ensure that the current day is the first day of the month.
443 is number of Sundays in January, if you want the Sundays on the first of the month, you have to change your code to:
if(date1.getDayOfMonth() == 1 && date1.getDayOfWeek() == SUNDAY) {
count++;
}
}
Sugestion: instead of walk over all days of each year, you can just add 1 month to the date util 12 month:
for (int i = 1901; i < 2001; i++) {
for(int mon =0; mon<12; mon++){
LocalDate date1= LocalDate.of(i,mon,1);
if(date1.getDayOfWeek() == SUNDAY) {
count++;
}
}
}
You are considering only January month from 1901 to 2000, which is incorrect, you should consider whether first day of every month from 1901 to 2000 was sunday or not.

Java Calendar shows wrong amount of weeks when first week of month is defined as week in which 1 occurs

I've made a function that should get the number of weeks for a given month. For January, May, July and October, it should return 5 weeks.
However, it returns 5 for March, June, September. and November. Surprisingly, the total amount of weeks are correct (52).
public static int getNofWeeksWithFirstWeekStartingWhenFirstDayOfMonthOccurs(Calendar calendar) {
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
calendar.roll(Calendar.DATE, true);
}
int currentMonth = calendar.get(Calendar.MONTH);
int nextMonth = (currentMonth + 1) % 12;
int prePreviousMonth = (currentMonth + 12 - 2) % 12;
int nofWeeks = 0;
do {
int month = calendar.get(Calendar.MONTH);
if (month == nextMonth) {
nofWeeks++;
}
if (month == prePreviousMonth) {
break;
}
calendar.roll(Calendar.WEEK_OF_YEAR, true);
} while (true);
return nofWeeks;
}
public static void main(String[] args) {
int numWeeks;
int totalWeeks=0;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2016);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.MONTH, Calendar.MAY);
numWeeks=getNofWeeksWithFirstWeekStartingWhenFirstDayOfMonthOccurs(calendar);
System.out.println("no of weeks " + numWeeks);
}
Output:
no of weeks 4
Month start is in Week that has first day. e.g.:
25 - 1 May
2 - 8 May
9 - 15 May
16 - 22 May
23 - 29 May
5 Weeks in May:
It sounds to me like you should:
Work out the first day of the month
Determine from that how many "extra" days are "borrowed" from the previous month (e.g. 0 if day 1 is a Monday; 1 if day 1 is a Tuesday etc)
Add that to the number of days in the regular month
Divide by 7 (with implicit truncation towards 0)
There's no need to do half the work you're currently doing.
Using java.util.Calendar, it would be something like:
// Note: day-of-week runs from Sunday (1) to Saturday (7).
// Entry 0 here is not used. We could do this without an array lookup
// if desired, but it's whatever code you think is clearest.
private static final int[] EXTRA_DAYS = { 0, 6, 0, 1, 2, 3, 4, 5 };
// Note: 0-based month as per the rest of java.util.Calendar
public static int getWeekCount(int year, int month) {
Calendar calendar = new GregorianCalendar(year, month, 1);
int dayOfWeekOfStartOfMonth = calendar.get(Calendar.DAY_OF_WEEK);
int extraDays = EXTRA_DAYS[dayOfWeekOfStartOfMonth];
int regularDaysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
int effectiveDaysInMonth = regularDaysInMonth + extraDays;
return effectiveDaysInMonth / 7;
}
If at all possible, I'd recommend using Joda Time or java.time instead, however.
With that code, the results for 2016 are:
January: 5
February: 4
March: 4
April: 4
May: 5
June: 4
July: 5
August: 4
September: 4
October: 5
November: 4
December: 4
From the comments I deduce that you want to count the number of weeks in a month starting at the 1st of the month.
You need to:
Set the day of the month to 1
add forward, not roll backward
start on Sunday instead of Monday
The code would be something like this:
public static int getNofWeeksWithFirstWeekStartingWhenFirstDayOfMonthOccurs(Calendar calendar) {
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
calendar.roll(Calendar.DATE, true);
}
int currentMonth = calendar.get(Calendar.MONTH);
int nextMonth = (currentMonth + 1) % 12;
int prePreviousMonth = (currentMonth + 12 - 2) % 12;
int nofWeeks = 0;
do {
int month = calendar.get(Calendar.MONTH);
if (month == currentMonth) {
nofWeeks++;
} else {
break;
}
calendar.add(Calendar.WEEK_OF_YEAR, 1);
} while (true);
return nofWeeks;
}
public static void main(String[] args) {
int numWeeks;
int totalWeeks=0;
for (int i = 0; i < 12; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2016);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.MONTH, i);
numWeeks=getNofWeeksWithFirstWeekStartingWhenFirstDayOfMonthOccurs(calendar);
System.out.println("no of weeks " + numWeeks);
}
}
Output:
no of weeks 5
no of weeks 4
no of weeks 4
no of weeks 4
no of weeks 5
no of weeks 4
no of weeks 5
no of weeks 4
no of weeks 4
no of weeks 5
no of weeks 4
no of weeks 4

claculate the number of days between two dates without libraries

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));
}
}

How to calculate "Friday before" in Java or Groovy?

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);
}

Categories