Given an instance of java.util.Date which is a Sunday. If there are 4 Sundays in the month in question, I need to figure out whether the chosen date is
1st Sunday of month
2nd Sunday of month
2nd last Sunday of month
Last Sunday of month
If there are 5 Sundays in the month in question, then I need to figure out whether the chosen date is
1st Sunday of month
2nd Sunday of month
3rd Sunday of month
2nd last Sunday of month
Last Sunday of month
I've had a look in JodaTime, but haven't found the relevant functionality there yet. The project is actually a Groovy project, so I could use either Java or Groovy to solve this.
Thanks,
Donal
Solutions given so far will tell you 1st, 2nd, 3rd, 4th, or 5th. But the question said he wanted to know "last" and "second to last". If the questioner really needs to know "last" etc, there's a little extra complexity. You have to figure out how many Sundays are in the month to know whether or not the 4th Sunday is the last. The first way to figure that out that occurs to me is:
GregorianCalendar gc=new GregorianCalendar();
gc.setTime(mydate);
gc.set(Calendar.DAY_OF_MONTH,1); // Roll back to first of month
int weekday=gc.get(Calendar.DAY_OF_WEEK); // day of week of first day
// Find day of month of first Sunday
int firstSunday;
if (weekday==Calendar.SUNDAY)
firstSunday=1;
else
firstSunday=weekday-Calendar.SUNDAY+6;
// Day of month of fifth Sunday, if it exists
int fifthSunday=firstSunday+7*4;
// Find last day of month
gc.add(Calendar.MONTH,1);
gc.add(Calendar.DATE,-1);
int lastDay=gc.get(DAY_OF_MONTH);
int sundays;
if (fifthSunday<lastDay)
sundays=4;
else
sundays=5;
That seems like rather a lot of work. Anybody see an easier way?
DAY_OF_WEEK_IN_MONTH
import java.sql.Date;
import java.util.Calendar;
public class Dow {
public static void main(String[] args) {
Date date = new Date( 2010, 4, 1 );
Calendar cal = Calendar.getInstance();
cal.setTime( date );
for ( int week = 0 ; week < 5 ; week++ ) {
System.out.println( cal.getTime() + " week:" + cal.get( Calendar.DAY_OF_WEEK_IN_MONTH ) );
cal.add( Calendar.WEEK_OF_MONTH, 1 );
}
}
}
> Sun May 01 00:00:00 CEST 3910 week:1
> Sun May 08 00:00:00 CEST 3910 week:2
> Sun May 15 00:00:00 CEST 3910 week:3
> Sun May 22 00:00:00 CEST 3910 week:4
> Sun May 29 00:00:00 CEST 3910 week:5
return dayOfMonth / 7 + 1;
MORE EDIT
Okay, taking Jay's comment in consideration, let's try this one:
int sundayId = dayOfMonth / 7 + 1;
if (sundayId == 1) {
return "1st";
} else if (sundayId == 2) {
return "2nd";
} else if (sundayId == 3) {
return ((dayOfMonth + 14 <= daysInMonth) ? "3rd" : "2nd Last");
} else if (sundayId == 4) {
return ((dayOfMonth + 7 <= daysInMonth) ? "2nd Last" : "Last");
} else {
return "Last";
}
whereas daysInMonth is calculated as follows:
if (month == 2) {
if (year % 100) {
return ((year % 400 == 0) ? 29 : 28);
} else {
return ((year % 4 == 0) ? 29 : 28);
}
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
} else {
return 31;
}
... or in some other way.
int sundayOfMonth = dayOfMonth / 7 + 1;
You can just use java.util.Calendar to do your date calculations:
import java.util.Calendar as CAL
def cal = CAL.getInstance(date)
def isFirst= cal.get(CAL.WEEK_OF_MONTH) == 1
def isSecond = cal.get(CAL.WEEK_OF_MONTH) == cal.getMaximum(CAL.WEEK_OF_MONTH)
Also, do not assume that there are only five weeks in a month with the Calendar object. For instance, the maximum weeks of 05/01/2010 would be 6.
EDIT: Here's my final version:
today = Calendar.instance
dayOfWeekInMonth = today.get(Calendar.DAY_OF_WEEK_IN_MONTH)
// move to last day of week occurrence in current month
today.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1)
maxDayOfWeekInMonth = today.get(Calendar.DAY_OF_WEEK_IN_MONTH)
dayOfWeekCount = ["1st", "2nd", "3rd", "2nd last", "Last"]
turningPoint = maxDayOfWeekInMonth - 2
if (dayOfWeekInMonth <= turningPoint) {
println dayOfWeekCount[dayOfWeekInMonth - 1]
}
else {
// use negative index to access list from last to first
println dayOfWeekCount[dayOfWeekInMonth - maxDayOfWeekInMonth - 1]
}
Related
I am working on a calendar project for a school seminar. It is supposed to print three months that go after each other. (You specify you want it to print January and it prints December of previous year, January and February).
I have this if statement for this, but I would like to simplify it into three lines of code. How do I do it? Is it possible?
if (month == 1) {
printMonth(12, year-1);
printMonth(month, year);
printMonth(month+1, year);
} else if (month == 12) {
printMonth(month-1, year);
printMonth(month, year);
printMonth(1, year+1);
} else {
printMonth(month-1, year);
printMonth(month, year);
printMonth(month+1, year);
}
Try using ternary operator:
printMonth(month == 1 ? 12 : month - 1, month == 1 ? year - 1 : year);
printMonth(month, year);
printMonth(month == 12 ? 1 : month + 1, month == 12 ? year + 1 : year);
You could use the Joda DateTime class to represent the current year/month, which is probably better than carrying years and month around as independent integers.
Then you could write:
printMonth(dt.minusMonths(1));
printMonth(dt);
printMonth(dt.plusMonths(1));
When I had such a problem myself, I tended to use an approach of combining year and month (also because I wanted to save some lines of code):
int monthAndYear = year * 12 + month;
printMonth(monthAndYear - 1);
printMonth(monthAndYear);
printMonth(monthAndYear + 1);
As you can see, this requires you to adjust the printMonth method, if it is possible of course.
private void printMonth(int monthAndYear) {
int year = monthAndYear / 12;
int month = monthAndYear % 12;
// other code...
}
And these are still four lines though...
As example If i got the month of August 2016 then i should get the start date as 01 Jul 2016 and end date as 30 September 2016(as this comes under 3rd quarter of this year).
Can anybody explain a logic for this.?
You could use Month and LocalDate's methods to get those dates:
public static void printStartEndQuarter(int year, Month month) {
LocalDate start = LocalDate.of(year, month.firstMonthOfQuarter(), 1);
Month endMonth = start.getMonth().plus(2);
LocalDate end = LocalDate.of(year, endMonth, endMonth.length(start.isLeapYear()));
System.out.println(start);
System.out.println(end);
}
public static void printStartEndQuarter(int year, int month) {
double thisMonth = (double)month;
String quarter = thisMonth/3 <= 1 ? "Quarter 1" : thisMonth/3 <= 2 ? "Quarter 2" : thisMonth/3 <= 3 ? "Quarter 3" : "Quarter 4";
if (month % 3 == 2) {
month = month - 1;
}
else if (month % 3 == 0) {
month = month - 2;
}
LocalDate start = LocalDate.of(year, month, 1);
Month endMonth = start.getMonth().plus(2);
LocalDate end = LocalDate.of(year, endMonth, endMonth.length(start.isLeapYear()));
System.out.println("Start Date====" + start);
System.out.println("End Date====" + end);
System.out.println("quarter====" + quarter);
}
Hope this will help some one and it will work for any test case.Thank You #fabin.
What exactly is it you do not understand? 3rd quarter of an year includes the months July, August and September, so start date of the quarter is the 1st day in July and end date is the last day of September. If you have February or March for example the start date will be 01 Jan 2016 and end date will be 31 Mar 2016. It is that simple.
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
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.
It's my first question on this site, but I always found this site really useful.
What I mean with my question is:
you ask the person to give a date (eg. Fill in a date [dd-mm-yyyy]:
16-10-2013)
you than have to ask an interval between 2
years (eg. Give an interval [yyyy-yyyy]:1800-2000)
When the program runs, it has to show what day of the week the given date is. In this case it was a Wednesday. Than the program has to look in which year, in between the interval, the date 16 October also fell on a Wednesday.
So in the end it has to look something like this:
Fill in a date: [dd-mm-yyyy]: 16-10-2013
Give an interval [yyyy-yyyy]: 1900-2000
16 October was a wednesday in the following years:
1905 1911 1916 1922 1933 1939 1944 1950 1961 1967 1972 1978 1989 1995 2000
The full date is Wednesday 16 October, 2013
The small (or biggest) problem is, I am not allowed to use the DATE.function in java.
If someone can help me with the second part I would be really really happy, cause I have no idea how I am supposed to do this
To find out what day of the week the given date falls, I use the Zeller Congruence
class Day {
Date date; //To grab the month and year form the Date class
//In this class I check whether the giving date is in the correct form
int day;
int year1; //First interval number
int year2; //Second interval number
final static String[] DAYS_OF_WEEK = {
"Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday"
};
public void dayWeekInterval{
int interval.year1;
int interval.year2;
for(int i = year1; year1 =< year2; year1++) {
//check if the day of the week in the giving year, is the same as the
//original year.
}
}
public void dayOfTheWeek {
int m = date.getMonth();
int y = date.getYear();
if (m < 3) {
m += 12;
y -= 1;
}
int k = y % 100;
int j = y / 100;
int day = ((q + (((m + 1) * 26) / 10) + k + (k / 4) + (j / 4)) +
(5 * j)) % 7;
return day;
}
public string ToString(){
return "" + DAYS_OF_WEEK[day] + day;
}
Hey, I changed my code a bit, but I don't know how to knot the tie. Also I forgot to mention, I am not allowed to use the Date and Calendar function of java... And I pretty much did something wrong with the outlook..
Just a simple formula to find day for given date dd - MM - yyxx is,
( dd + m + xx + (xx/4) + (yy%4) ) % 7
% is modulus operator which is remainder in general
The answer got above will tell you day of week i.e. 0 : Mon 1: Tue .... 6 for Sun
Here,
dd - Date given
m - month value which is shown down in list calculated with MM value
yy - first two digits of supplied year
xx - last two digits of year
Now, m value calculation is,
0 for Jan and Oct
1 for May
2 for August
3 for Feb, March and Nov
4 for June
5 for Sept and Dec
6 for July and April
Remember if month supplied is Jan or Feb and the year supplied is leap then subtract 1 from m value in above table i.e. -1 for Jan and 2 for Feb
Leap Year Calculation is
if (yyyy % 4 == 0)
{
if( yyyy % 100 == 0)
{
return (yyyy % 400) == 0;
}
else
return true;
}
I hope rest of programming you can do.
This will help you find the day of week for supplied date and now you just need to add loop for all the years.
You cannot use Datebut can you use Calendar? Then this would be your code:
Calendar c = Calendar.getInstance();
c.set(2013, 9, 16); // month starts at zero
System.out.printf("Original date is: %tc\n", c);
int weekday = c.get(Calendar.DAY_OF_WEEK);
System.out.printf("Weekday of original date is [by number] %d\n", weekday);
for(int year = 1800; year < 2000; year++) {
c.set(Calendar.YEAR, year);
if(weekday == c.get(Calendar.DAY_OF_WEEK))
System.out.printf("%tc was same weekday!\n", c);
}