Get the first Monday of a month - java

I want to get the day on which the first Monday of a specific month/year will be.
What I have:
I basically have two int variables, one representing the year and one representing the month.
What I want to have:
I want to know the first Monday in this month, preferably as an int or Integer value.
For example:
I have 2014 and 1 (January), the first Monday in this month was the 6th, so I want to return 6.
Problems:
I thought I could do that with the Calendar but I am already having trouble setting up the calendar with only Year and Month available. Furthermore, I'm not sure how to actually return the first Monday of the month/year with Calendar.
I already tried this:
Calendar cal = Calendar.getInstance();
cal.set(this.getYear(),getMonth(), 1);
int montag = cal.getFirstDayOfWeek();
for( int j = 0; j < 7; j++ ) {
int calc = j - montag;
if( calc < 0 ) {
calc += 6;
}
weekDays[calc].setText(getDayString(calc));
}

Java.time
Use java.time library built into Java 8 and TemporalAdjuster. See Tutorial.
import java.time.DayOfWeek;
import java.time.LocalDate;
import static java.time.temporal.TemporalAdjusters.firstInMonth;
LocalDate now = LocalDate.now(); //2015-11-23
LocalDate firstMonday = now.with(firstInMonth(DayOfWeek.MONDAY)); //2015-11-02 (Monday)
If you need to add time information, you may use any available LocalDate to LocalDateTime conversion like
firstMonday.atStartOfDay() # 2015-11-02T00:00

getFirstDayOfWeek() returns which day is used as the start for the current locale. Some people consider the first day Monday, others Sunday, etc.
This looks like you'll have to just set it for DAY_OF_WEEK = MONDAY and DAY_OF_WEEK_IN_MONTH = 1 as that'll give you the first Monday of the month. To do the same for the year, first set the MONTH value to JANUARY then repeat the above.
Example:
private static Calendar cacheCalendar;
public static int getFirstMonday(int year, int month) {
cacheCalendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
cacheCalendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
cacheCalendar.set(Calendar.MONTH, month);
cacheCalendar.set(Calendar.YEAR, year);
return cacheCalendar.get(Calendar.DATE);
}
public static int getFirstMonday(int year) {
return getFirstMonday(year, Calendar.JANUARY);
}
Here's a simple JUnit that tests it: http://pastebin.com/YpFUkjQG

First of all you should know the latest version of java i.e. JAVA8
Get familiar with LocalDate in JAVA8
Then only go through below code
public class Test {
public static void main(String[] args) {
LocalDate date=LocalDate.of(2014,1, 1);
for(int i=0;i<date.lengthOfMonth();i++){
if("Monday".equalsIgnoreCase(date.getDayOfWeek().toString())){
break;
}else{
date=date.plusDays(1);
}
}
System.out.println(date.getDayOfMonth());
}
}

Joda-Time
The Joda-Time library offers a class, LocalDate, for when you need only a date without a time-of-day. The method getDayOfWeek returns a number you can compare to the constant MONDAY.
LocalDate localDate = new LocalDate( year, month, 1 );
while ( localDate.getDayOfWeek() != DateTimeConstants.MONDAY ) {
localDate = localDate.plusDays( 1 );
}
int firstMonday = localDate.getDayOfMonth();
Immutable Syntax
For thread-safety, Joda-Time uses immutable objects. So rather than modify field values in an existing object, we create a new instance based on the original.
java.time
As another answer by Abhishek Mishra says, the new java.time package bundled with Java 8 also offers a LocalDate class similar to Joda-Time.

The method getFirstDayOfWeek() is not helpful. Quoting its javadoc:
Gets what the first day of the week is; e.g., SUNDAY in the U.S., MONDAY in France
The following tested method uses modulus arithmetic to find the day of the month of the first Monday:
public static long getMondaysDay(int year, int month) {
try {
Date d = new SimpleDateFormat("d-M-yyyy").parse("1-" + month + "-" + year);
long epochMillis = d.getTime() + TimeZone.getDefault().getOffset(d.getTime());
return (12 - TimeUnit.MILLISECONDS.toDays(epochMillis) % 7) % 7;
} catch (ParseException ignore) { return 0; } // Never going to happen
}
Knowing that the first day of the epoch was Thursday, this works by using modulus arithmetic to calculate the day of the epoch week, then how many days until the next Monday, then modulus again in case the first falls before Thursday. The magic number 12 is 4 (the number of days from Thursday to Monday) plus 1 because days of the month start from 1 plus 7 to ensure positive results after subtraction.

The simplest way is:
LocalDate firstSundayOfNextMonth = LocalDate
.now()
.with(firstDayOfNextMonth())
.with(nextOrSame(DayOfWeek.MONDAY));

Here is a general function to get the nth DAY_OF_WEEK of a given month. You can use it to get the first Monday of any given month.
import java.util.Calendar;
public class NthDayOfWeekOfMonth {
public static void main(String[] args) {
// get first Monday of July 2019
Calendar cal = getNthDayOfWeekOfMonth(2019,Calendar.JULY,1,Calendar.MONDAY);
System.out.println(cal.getTime());
// get first Monday of August 2019
cal = getNthDayOfWeekOfMonth(2019,Calendar.AUGUST,1,Calendar.MONDAY);
System.out.println(cal.getTime());
// get third Friday of September 2019
cal = getNthDayOfWeekOfMonth(2019,Calendar.SEPTEMBER,3,Calendar.FRIDAY);
System.out.println(cal.getTime());
}
public static Calendar getNthDayOfWeekOfMonth(int year, int month, int n, int dayOfWeek) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE,0);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.YEAR,year);
cal.set(Calendar.MONTH,month);
cal.set(Calendar.DAY_OF_MONTH,1);
int dayDiff = dayOfWeek-cal.get(Calendar.DAY_OF_WEEK);
if (dayDiff<0) {
dayDiff+=7;
}
dayDiff+=7*(n-1);
cal.add(Calendar.DATE, dayDiff);
return cal;
}
}
Output:
Mon Jul 01 00:00:00 EDT 2019
Mon Aug 05 00:00:00 EDT 2019
Fri Sep 20 00:00:00 EDT 2019

Lamma Date library is very good for this use case.
#Test
public void test() {
assertEquals(new Date(2014, 1, 6), firstMonday(2014, 1));
assertEquals(new Date(2014, 2, 3), firstMonday(2014, 2));
assertEquals(new Date(2014, 3, 3), firstMonday(2014, 3));
assertEquals(new Date(2014, 4, 7), firstMonday(2014, 4));
assertEquals(new Date(2014, 5, 5), firstMonday(2014, 5));
assertEquals(new Date(2014, 6, 2), firstMonday(2014, 6));
}
public Date firstMonday(int year, int month) {
Date firstDayOfMonth = new Date(year, month, 1);
return firstDayOfMonth.nextOrSame(DayOfWeek.MONDAY);
}

Calendar calendar = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("MMM/dd/YYYY");
calendar.set(Calendar.MONTH,Calendar.JUNE);
calendar.set(Calendar.DAY_OF_MONTH,1);
int day = (Calendar.TUESDAY-calendar.get(Calendar.DAY_OF_WEEK));
if(day<0){
calendar.add(Calendar.DATE,7+(day));
}else{
calendar.add(Calendar.DATE,day);
}
System.out.println("First date is "+sdf.format(calendar.getTime()));

Get the All Monday of a month
public class AllMonday {
public static void main(String[] args){
System.out.println(weeksInCalendar(YearMonth.now()));
}
public static List<LocalDate> weeksInCalendar(YearMonth month) {
List<LocalDate> firstDaysOfWeeks = new ArrayList<>();
for (LocalDate day = firstDayOfCalendar(month);
stillInCalendar(month, day); day = day.plusWeeks(1)) {
firstDaysOfWeeks.add(day);
}
return firstDaysOfWeeks;
}
private static LocalDate firstDayOfCalendar(YearMonth month) {
DayOfWeek FIRST_DAY_OF_WEEK = DayOfWeek.of(1);
System.out.println( month.atDay(1).with(FIRST_DAY_OF_WEEK));
return month.atDay(1).with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
}
private static boolean stillInCalendar(YearMonth yearMonth, LocalDate day) {
System.out.println(!day.isAfter(yearMonth.atEndOfMonth()));
return !day.isAfter(yearMonth.atEndOfMonth());
}
}

Related

Get correct week Start date and end date when monday , tuesday falls in last year last week

I am getting week number and year from DB(using function DATE_PART('week',alarm_date - (interval '1 days') * 0) AS week, DATE_PART('year',alarm_date) AS yearNo , ISO compliant) and on the basis of week number and year i want to calculate weekStartDate and weekEndDate between user provided startdate and end date with week start date for example {"startDate":"2021-12-28","endDate":"2022-01-06","weekStartDay":"Sunday"}
private String getWeek(LocalDate startTime, LocalDate endTime, int yearNo, int weekNumber, int weekStartDay){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
// make it ISO compliant since postgres is using ISO time to calculate week number
cal.setMinimalDaysInFirstWeek(4);
cal.set(Calendar.YEAR, yearNo);
cal.set(Calendar.WEEK_OF_YEAR, weekNumber);
//ISO week starts on Monday and ends on Sunday
cal.set(Calendar.DAY_OF_WEEK, weekStartDay);// weekStartDay configurabale, as per
//user input Calendar.SUNDAY or Calendar.MONDAY or Calendar.TUEDAY; etc
String weekStartDate = sdf.format(cal.getTime());
cal.add(Calendar.DATE, 6);
String weekEndDate = sdf.format(cal.getTime());
LocalDate weekStart = LocalDate.of(Integer.valueOf(weekStartDate.substring(0, 4)),
Integer.valueOf(weekStartDate.substring(5, 7)), Integer.valueOf(weekStartDate.substring(8)));
if(weekStart.isBefore(startTime)) {
weekStart = startTime;
}
LocalDate weekEnd = LocalDate.of(Integer.valueOf(weekEndDate.substring(0, 4)),
Integer.valueOf(weekEndDate.substring(5, 7)), Integer.valueOf(weekEndDate.substring(8)));
if(weekEnd.isAfter(endTime)) {
weekEnd = endTime;
}
String weekStr = weekStart.toString()+"_"+weekEnd.toString();
return weekStr;
}
But when weekStartDay falls in lastweek of previous year then it gives the wrong vale of weekStartDate and weekStartEnd so please suggest me how to set yearnumber in java
Avinash, not the full answer but in-line with what Tom mentioned. A lot of convinient date time API's can be used since Java-8. Please feel free to customize this approach for the exact logic you may need
import java.time.DayOfWeek;
import java.time.temporal.ChronoField;
import java.time.temporal.IsoFields;
import static java.time.temporal.IsoFields.WEEK_OF_WEEK_BASED_YEAR;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.temporal.TemporalAdjusters;
public class SO75013931 {
public static void main(String[] args) {
System.out.println(getWeekStart(LocalDate.parse("2021-12-28"),DayOfWeek.SUNDAY));
System.out.println(getWeekEnd(LocalDate.parse("2021-12-28"),DayOfWeek.SUNDAY));
}
//28-12-2021 TO 01-01-2022 && 02-01-2022 to 06-01-2022
private static String getWeekStart(LocalDate localDate, DayOfWeek weekStartDay) {
LocalDate weekStart = localDate.with(TemporalAdjusters.previous(weekStartDay));
return weekStart.isBefore(localDate) ? localDate.toString(): weekStart.toString();
}
private static String getWeekEnd(LocalDate localDate, DayOfWeek weekStartDay) {
LocalDate weekEnd = localDate.with(TemporalAdjusters.next(weekStartDay.minus(1)));
return weekEnd.isBefore(localDate) ? localDate.toString(): weekEnd.toString();
}
}
This would give
2021-12-28
2022-01-01
Again, the idea was to recommend usage of these API's as opposed to older util API's

Simple date format day of week displays same day

I'm having issues with the below code displays Thursday as the dayOfTheWeek regardless of the date. Any ideas where I've gone wrong with this?
public void CreatePlan() {
editPlanName = findViewById(R.id.editPlanName);
String plan_name = editPlanName.getText().toString();
DatabaseManager db;
int day = datepicker.getDayOfMonth();
int month = datepicker.getMonth();
int year = datepicker.getYear();
SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
Integer d_name = day;
Integer plan_recipe = 0;
Log.d("Date", String.valueOf(d_name));
String dayOfTheWeek = sdf.format(d_name);
String date = day + "/" + month + "/" +year;
db = new DatabaseManager(getApplicationContext());
Log.d("Recipe name", recipe_name);
db.createPlanRecipe(d_name, date, dayOfTheWeek, recipe_name);
db.createPlan(plan_name, plan_recipe);
}
… Any ideas where I've gone wrong with this?
day in your program is the day of the month from 1 to 31. Therefore d_name holds this number too.
Your SimpleDateFormat accepts formatting a number as a date and time expecting a count of milliseconds since the epoch of January 1, 1970 at 00:00 in UTC. So it will always format a date and time within the first 31 milliseconds after the epoch. Depending on your time zone the point in time that you format falls either on Wednesday, December 31, 1969 or on Thursday, January 1, 1970. So you will either always get Wednesday or always Thursday.
SimpleDateFormat.format(Object) accepts either a Date or a Number. Since Integer is a subclass of Number, it works as described.
The SimpleDateFormat class is notoriously troublesome, you have seen but a small corner of the problems that people often have with it. The Calendar class used in one other answer is poorly designed too. Both are long outdated. I suggest you look into java.time, the modern Java date and time API instead.
Further link: My answer to another question about getting the day of week from an Android date picker.
You are getting the value of the day-of-the-month, the month and the year in the following lines of code but you are not setting these values into the Calendar object which is supposed to give you other information (e.g. the day-of-week) by processing these values:
int day = datepicker.getDayOfMonth();
int month = datepicker.getMonth();
int year = datepicker.getYear();
So, before you try to get any other information from the Calendar object, set these values to the object as shown below:
// Set the picked values into an instance of Calendar
Calendar calendar = Calendar.getInstance();
calendar.clear();// Make sure to call this to reset all fields
calendar.set(year, month - 1, day);// Make sure to decrease month by 1
Now, your rest of code will work as you are expecting e.g. let's say you select 4 as the day-of-the-month, 10 as the month, and 2020 as the year, the following code will give you Sunday as the day-of-the-week.
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class Main {
public static void main(String[] args) {
int day = 4;
int month = 10;
int year = 2020;
// Set the picked values into an instance of Calendar
Calendar calendar = Calendar.getInstance();
calendar.clear();// Make sure to call this to reset all fields
calendar.set(year, month - 1, day);// Make sure to decrease month by 1
System.out.println(calendar.getTime());
// Your desired format
SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
// The day-of-the-week for the specified date
String dayOfTheWeek = sdf.format(calendar.getTime());
System.out.println(dayOfTheWeek);
}
}
Output:
Sun Oct 04 00:00:00 BST 2020
Sunday
Note that I have decreased the month (picked from the date-picker) by 1 because java.util date-time API is based on 0 as the month of January.
A piece of advice:
I recommend you switch from the outdated and error-prone java.util date-time API and SimpleDateFormat to the modern java.time date-time API and the corresponding formatting API (from the package, java.time.format). Learn more about the modern date-time API from Trail: Date Time.
If your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
By using the modern date-time API:
import java.time.LocalDate;
import java.time.format.TextStyle;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
int dayOfMonth = 4;
int month = 10;
int year = 2020;
// Instantiate a LocalDate object using the picked values
LocalDate date = LocalDate.of(year, month, dayOfMonth);
// The day-of-the-week for the specified date
String dayOfTheWeek = date.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH);
System.out.println(dayOfTheWeek);
}
}
Output:
Sunday
You have to create Date from your datepicker, then format it to find day like below:
int day = datePicker.getDayOfMonth();
int month = datePicker.getMonth();
int year = datePicker.getYear();
Calendar calendar = Calendar.getInstance();
calendar.set(year, month - 1, day);
SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
dayOfTheWeek = sdf.format(calendar.getTime());

Get third friday of a month

I develop a local calendar for my application. but there is an issue with monthly repeat event (day of week).
When i create an event starting on 16-9-2016(16 SEP 2016 FRIDAY) and repeating Third Friday of each month. but next month it create on second
Friday 14-10-2016 (This is the issue). next month it will be on third Friday.
my code is
public Date nthWeekdayOfMonth(int dayOfWeek, int month, int year, int week, TimeZone timeZone) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(timeZone);
calendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
calendar.set(Calendar.WEEK_OF_MONTH, week);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.YEAR, year);
return calendar.getTime();
}
I know the issue. but i don`t know how to fix it.. is there any way to fix it ?
You code seems to be working completely fine, there is nothing that is going wrong from what I can see, it may be that your parameters are wrong.
It is important to note that MONTH and DAY are 0-based so, 0 = January and 0 = Sunday so your parameters for getting the third friday should look like the following:
nthWeekdayOfMonth(6, 9, 2016, 3, TimeZone.getTimeZone("Europe/London"));
Which returns the following output:
Fri Oct 21 11:06:33 BST 2016
To break it down:
Day of week is 6, because Sunday = 0.
Month is 9 - i.e. October
Year is normal - 2016
Week is NOT 0-based so 3rd week will be index 3
TimeZone as normal
Please see the Calendar documentation for reference.
EDIT
So for some reason, it works on my machine but it doesn't on others; I don't know what the issue could be with that but using DAY_OF_WEEK_IN_MONTH seems to be a better option for this:
public static Date nthWeekdayOfMonth(int dayOfWeek, int month, int year, int week, TimeZone timeZone) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(timeZone);
calendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
//calendar.set(Calendar.WEEK_OF_MONTH, week);
calendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, week);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.YEAR, year);
return calendar.getTime();
}
I usually use GregorianCalendar but Calendar should work just fine.
This should (hopefully) work for the most part, I've tested it on other machines and ideone.
I could propose next decision:
public Date nthWeekdayOfMonth(int dayOfWeek, int month, int year, int week, TimeZone timeZone) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(timeZone);
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, 1);
// add +1 to week if first weekday of mounth > dayOfWeek
int localWeek = week;
if (calendar.get(calendar.DAY_OF_WEEK) > dayOfWeek) {
localWeek++;
}
calendar.set(Calendar.WEEK_OF_MONTH, localWeek);
calendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
return calendar.getTime();
}
for:
System.out.println(nthWeekdayOfMonth(Calendar.FRIDAY, Calendar.SEPTEMBER, 2016, 3, TimeZone.getTimeZone("Europe/London")));
System.out.println(nthWeekdayOfMonth(Calendar.FRIDAY, Calendar.OCTOBER, 2016, 3, TimeZone.getTimeZone("Europe/London")));
System.out.println(nthWeekdayOfMonth(Calendar.FRIDAY, Calendar.NOVEMBER, 2016, 3, TimeZone.getTimeZone("Europe/London")));
it returns:
Fri Sep 16 19:41:23 YEKT 2016
Fri Oct 21 19:41:23 YEKT 2016
Fri Nov 18 20:41:23 YEKT 2016
Java 8
LocalDate thirdFriday = java.time.LocalDate.now()
.with(TemporalAdjusters.firstDayOfMonth())
.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))
.plusDays(14)
java.time
java.time, the modern Java date and time API, has a built-in adjuster for that:
public LocalDate nthWeekdayOfMonth(DayOfWeek dayOfWeek, Month month, int year, int week) {
return LocalDate.of(year, month, 15)
.with(TemporalAdjusters.dayOfWeekInMonth(week, dayOfWeek));
}
Try it out:
System.out.println(nthWeekdayOfMonth(DayOfWeek.FRIDAY, Month.OCTOBER, 2016, 3));
Output:
2016-10-21
Please also note that the arguments that I pass to the method are much more telling.
Link: Oracle tutorial: Date Time explaining how to use java.time.
This is a functioning Java 8 implementation. The example from KayV did not work for September 2017, but it helped me to head in the right direction.
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class OptionExpirationDates {
public static void main(String[] args) {
LocalDate startDate = LocalDate.of(2017, Month.FEBRUARY, 15);
List<LocalDate> optionExDates = optionExpirationDates(startDate, 20);
for (LocalDate temp : optionExDates) {
System.out.println(temp);
}
}
public static List<LocalDate> optionExpirationDates(LocalDate startDate, int limit) {
return Stream.iterate(startDate, date -> date.plusDays(1))
.map(LocalDate -> LocalDate.with(TemporalAdjusters.firstDayOfMonth()).minusDays(1)
.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)).plusWeeks(2))
.distinct()
.limit(limit)
.collect(Collectors.toList());
}
}
Perhaps we should also mention that this code is to calculate an option expiration date, so that the search engine can pick it up.
Java 8 way of doing this is as follows:
LocalDate thirdFriday = LocalDate
.now()
.with(lastDayOfMonth())
.with(previous(DayOfWeek.FRIDAY)).minusDays(7);
To take a different approach. If the first day of the month is a Saturday, then the third Friday is the 21st of that month. Extend this for the seven possible days:
Saturday 1st -> Friday 21st.
Sunday 1st -> Friday 20th
Monday 1st -> Friday 19th
Tuesday 1st -> Friday 18th
Wednesday 1st -> Friday 17th
Thursday 1st -> Friday 16th
Friday 1st -> Friday 15th
You just need to check what day of the week the first of the month is.
Below function can be used to calculate third friday of month using joda time. The function is verbose for sake of clarity on logic.
public static DateTime thirdFridayOfMonth(int year, int month) {
DateTime firstDayOfMonth = new DateTime(year, month, 1, 0, 0);
MutableDateTime mFirstDayOfMonth = new MutableDateTime(firstDayOfMonth);
//Now calculate days to 1st friday from 1st day of month
int daysToFirstFridayOfMonth = mFirstDayOfMonth.dayOfWeek().get() <= 5 ? (5 - mFirstDayofMonth.dayOfWeek().get()) : (7 - mFirstDayofMonth.dayOfWeek().get() + 5);
//move to first 1st friday of month
mFirstDayOfMonth.addDays(daysToFirstFridayOfMonth);
//move to 3rd friday of month
mFirstDayOfMonth.addWeeks(2);
return mFirstDayOfMonth.toDateTime();
}
with Java LocalDateTime
LocalDateTime firstDayOfMonth = LocalDateTime.of(year, Month.of(month), 1, 0, 0);
// Returns 1-7 (NOT 0-6)
int firstDayValue = firstDayOfMonth.getDayOfWeek().getValue();
int thirdFriday = 20 + firstDayValue / 6 * 7 - firstDayValue;
return LocalDateTime.of(year, Month.of(month), thirdFriday, 0, 0);

Convert month name to Date range

I need to convert Monthname + Year to a valid date range. It needs to work with leap years etc.
Examples
getDateRange("Feb",2015)
should find the range 2015-02-01 -- 2015-02-28
While
getDateRange("Feb",2016)
should find the range 2016-02-01 -- 2016-02-29
In Java 8, you can do that using TemporalAdjusters,
LocalDate firstDate= date.with(TemporalAdjusters.firstDayOfMonth());
LocalDate lastDate= date.with(TemporalAdjusters.lastDayOfMonth());
If you have only year and month, it is better to use YearMonth. From YearMonth you can easily get length of that month.
YearMonth ym= YearMonth.of(2015, Month.FEBRUARY);
int monthLen= ym.lengthOfMonth();
Java 8 made Date-Time operations very simple.
For Java 7 and below you could get away with something like this;
void getDate(String month, int year) throws ParseException {
Date start = null, end = null;
//init month and year
SimpleDateFormat sdf = new SimpleDateFormat("MMM");
Date parse = sdf.parse(month);
Calendar instance = Calendar.getInstance();
instance.setTime(parse);
instance.set(Calendar.YEAR, year);
//start is default first day of month
start = instance.getTime();
//calculate end
instance.add(Calendar.MONTH, 1);
instance.add(Calendar.DAY_OF_MONTH, -1);
end = instance.getTime();
System.out.println(start + " " + end);
}
The output would be for "Feb", 2015:
Sun Feb 01 00:00:00 EET 2015
Sat Feb 28 00:00:00 EET 2015
Java 7 solution with default Java tools:
public static void getDateRange(String shortMonth, int year) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("MMM yyyy", Locale.ENGLISH);
// the parsed date will be the first day of the given month and year
Date startDate = format.parse(shortMonth + " " + year);
Calendar calendar = Calendar.getInstance();
calendar.setTime(startDate);
// set calendar to the last day of this given month
calendar.set( Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
// and get a Date object
Date endDate = calendar.getTime();
// do whatever you need to do with your dates, return them in a Pair or print out
System.out.println(startDate);
System.out.println(endDate);
}
Try (untested):
public List<LocalDate> getDateRange(YearMonth yearMonth){
List<LocalDate> dateRange = new ArrayList<>();
IntStream.of(yearMonth.lengthOfMonth()).foreach(day -> dateRange.add(yearMonth.at(day));
return dateRange
}
Java 8 provides new date API as Masud mentioned.
However if you are not working under a Java 8 environment, then lamma date is a good option.
// assuming you know the year and month already. Because every month starts from 1, there should be any problem to create
Date fromDt = new Date(2014, 2, 1);
// build a list containing each date from 2014-02-01 to 2014-02-28
List<Date> dates = Dates.from(fromDt).to(fromDt.lastDayOfMonth()).build();

Java Calendar: calculate start date and end date of the previous week

What is most convenient and shortest way to get start and end dates of the previous week?
Example: today is 2011-10-12 (input data),but I want to get 2011-10-03 (Monday's date of previous week) and 2011-10-09 (Sunday's date of previous week).
Here's another JodaTime solution. Since you seem to want Dates only (not timestamps), I'd use the DateMidnight class:
final DateTime input = new DateTime();
System.out.println(input);
final DateMidnight startOfLastWeek =
new DateMidnight(input.minusWeeks(1).withDayOfWeek(DateTimeConstants.MONDAY));
System.out.println(startOfLastWeek);
final DateMidnight endOfLastWeek = startOfLastWeek.plusDays(6);
System.out.println(endOfLastWeek);
Output:
2011-10-12T18:13:50.865+02:00
2011-10-03T00:00:00.000+02:00
2011-10-10T00:00:00.000+02:00
public static Calendar firstDayOfLastWeek(Calendar c) {
c = (Calendar) c.clone();
// last week
c.add(Calendar.WEEK_OF_YEAR, -1);
// first day
c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
return c;
}
public static Calendar lastDayOfLastWeek(Calendar c) {
c = (Calendar) c.clone();
// first day of this week
c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
// last day of previous week
c.add(Calendar.DAY_OF_MONTH, -1);
return c;
}
I would go for #maerics answer if third party library is not involved. I have to replace roll() method with add() method as roll will leave the higher field unchanged. e.g., 22nd August will be obtained from 1st August being rolled -7 days. Note the month remain unchanged.
The source code goes as below.
public static Calendar[] getLastWeekBounds(Calendar c) {
int cdow = c.get(Calendar.DAY_OF_WEEK);
Calendar lastMon = (Calendar) c.clone();
lastMon.add(Calendar.DATE, -7 - (cdow - Calendar.MONDAY));
Calendar lastSun = (Calendar) lastMon.clone();
lastSun.add(Calendar.DATE, 6);
return new Calendar[] { lastMon, lastSun };
}
You can use the Calendar.roll(int,int) method with arguments Calendar.DATE and an offset for the current day of week:
public static Calendar[] getLastWeekBounds(Calendar c) {
int cdow = c.get(Calendar.DAY_OF_WEEK);
Calendar lastMon = (Calendar) c.clone();
lastMon.roll(Calendar.DATE, -7 - (cdow - Calendar.MONDAY));
Calendar lastSun = (Calendar) lastMon.clone();
lastSun.roll(Calendar.DATE, 6);
return new Calendar[] { lastMon, lastSun };
}
This function returns an array of two Calendars, the first being last week's Monday and last week's Sunday.
Wow, the Java date APIs are terrible.
Calendar today = Calendar.getInstance();
Calendar lastWeekSunday = (today.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) ? today.roll(-7): today.roll(Calendar.DAY_OF_YEAR, Calendar.SUNDAY - today.get(Calendar.DAY_OF_WEEK));
Calendar lastWeekMonday = lastWeekSunday.roll( Calendar.DAY_OF_YEAR, -6 );
Using Joda:
DateTime input;
DateTime startOfLastWeek = input.minusWeeks(1).minusDays(input.getDayOfWeek()-1);
DateTime endOfLastWeek = input.minusWeeks(1).plusDays(input.getDayOfWeek()+1);
DateTime endOfLastWeek = startOfLastWeek.plusDays(6);
EDIT:
Joda does not allow a different first day of the week, but strictly sticks to the ISO standard, which states that a week always starts on Monday. However, if you need to make that configurable, you could pass the desired first day of the week as a parameter. See the above link for some other ideas.
public DateTime getFirstDayOfPreviousWeek(DateTime input)
{
return getFirstDayOfPreviousWeek(input, DateTimeConstants.MONDAY);
}
public DateTime getFirstDayOfPreviousWeek(DateTime input, int firstDayOfWeek)
{
return new DateTime(input.minusWeeks(1).withDayOfWeek(firstDayOfWeek));
}
public DateTime getLastDayOfPreviousWeek(DateTime input)
{
return getLastDayOfPreviousWeek(input, DateTimeConstants.MONDAY);
}
public DateTime getLastDayOfPreviousWeek(DateTime input, int firstDayOfWeek)
{
return new DateTime(getFirstDayOfPreviousWeek(input, firstDayOfWeek).plusDays(6));
}

Categories

Resources