I have the week number, its curresponding year and dayOfWeek number(i.e. 1 for Monday, 2 for Tuesday and so on). Is there a way to find the date with this information in java?
Following is a method I found online.
int week = 51;
LocalDate wkstart = LocalDate.now().with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, week);
LocalDate mon = wks.plusDays(1);
LocalDate tue = wks.plusDays(2);
LocalDate wed = wks.plusDays(3);
LocalDate thu = wks.plusDays(4);
LocalDate fri = wks.plusDays(5);
LocalDate sat = wks.plusDays(6);
LocalDate wkend = wks.plusDays(7);
But then realised that wkstart is storing the current date instead of the start of the week.
Is there a better way of doing this?
Instead of adding a number of days to wkstart, use with again to set the day of week. For example:
LocalDate date = LocalDate.now()
.with(WeekFields.ISO.weekBasedYear(), 2018) // year
.with(WeekFields.ISO.weekOfWeekBasedYear(), 51) // week of year
.with(WeekFields.ISO.dayOfWeek(), DayOfWeek.MONDAY.getValue()); // day of week
tl;dr
LocalDate localDate =
YearWeek // Represent an entire week of a week-based year per the ISO 8601 standard definition of a week.
.of( // Instantiate a `YearWeek` object.
2019 , // Specify the week-based year number, NOT the calendar year.
51 // Specify the week number, 1-52 or 1-53.
)
.atDay(
DayOfWeek.of( 1 ) // The value 1 yields a `DayOfWeek.MONDAY` object.
)
;
org.threeten.extra.YearWeek
The Answer by Sweeper looks correct. But there is a more specialized class for this.
If doing much work with weeks of week-based years per the ISO 8601 definition of week, use the YearWeek class found in the ThreeTen-Extra library. This library adds extra functionality to the java.time classes built into Java 8 and later.
Determine the week.
YearWeek yearWeek = YearWeek.of( 2019 , 51 ) ;
Get a LocalDate for the day-of-week within that week.
LocalDate localDate = yearWeek.atDay( DayOfWeek.MONDAY ) ;
For the day-of-week, you should be using DayOfWeek enum objects in your code rather than mere integer numbers. To get a DayOfWeek from an original number 1-7 for Monday-Sunday, call DayOfWeek.of( x ).
DayOfWeek dow = DayOfWeek.of( 1 ) ; // 1 = Monday, 7 = Sunday.
Putting that all together we get this one-liner.
LocalDate localDate = YearWeek.of( 2019 , 51 ).atDay( DayOfWeek.of( 1 ) ) ;
To be clear… The ISO 8601 definition of a week is:
Week # 1 contains the first Thursday of the year.
Weeks start on a Monday, ending on a Sunday.
A year has either 52 or 53 complete 7-day weeks.
The first/last weeks of the week-based year may contain the trailing/leading days of the previous/next calendar years. Thus, the calendar year of those days differ from the week-based year.
It also depends on the Locale.
Note that the first day of the week is Locale-dependent e.g. it is Monday in the UK while Sunday in the US. As per the ISO 8601 standards, it is Monday. For comparison, check the US calendar and the UK calendar. Accordingly, the date will vary as shown in the example below:
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// Test
int weekNumber = 34;
int year = 2021;
System.out.println(getLocalDate(weekNumber, DayOfWeek.TUESDAY, year, Locale.UK));
System.out.println(getLocalDate(weekNumber, DayOfWeek.TUESDAY, year, Locale.US));
System.out.println(getLocalDate(weekNumber, DayOfWeek.SUNDAY, year, Locale.UK));
System.out.println(getLocalDate(weekNumber, DayOfWeek.SUNDAY, year, Locale.US));
}
static LocalDate getLocalDate(int weekNumber, DayOfWeek dow, int year, Locale locale) {
return LocalDate.of(year, 2, 1)
.with(dow)
.with(WeekFields.of(locale).weekOfWeekBasedYear(), weekNumber);
}
}
Output:
2021-08-24
2021-08-17
2021-08-29
2021-08-15
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and 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.
Related
I am working on a project. There I should find the total weeks of a year. I tried with the following code, but I get the wrong answer: 2020 has 53 weeks, but this code gives 52 weeks.
Where have I gone wrong in this code?
package com.hib.mapping;
import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.joda.time.DateTime;
public class TestWeek {
public static void main(String args[]) {
System.out.println(getWeeks());
}
public static int getWeeks() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2020);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
GregorianCalendar gregorianCalendar = new GregorianCalendar();
int weekDay = cal.get(Calendar.DAY_OF_WEEK) - 1;
if (gregorianCalendar.isLeapYear(2020)) {
if (weekDay == Calendar.THURSDAY || weekDay == Calendar.WEDNESDAY)
return 53;
else
return 52;
} else {
if (weekDay == Calendar.THURSDAY)
return 53;
else
return 52;
}
}
}
Output:
52
tl;dr
For a standard ISO 8601 week, use the YearWeek class from ThreeTen-Extra library with a ternary statement.
YearWeek // Represents an entire week of a week-based-year.
.of( 2020 , 1 ) // Pass the number of the week-based-year (*not* calendar year), and a week number ranging from 1 to 52 or 1 to 53.
.is53WeekYear() // Every standard week-based-year has either 52 or 52 complete weeks.
? 53 // Ternary statement returns 53 if the predicate returns True, …
: 52 // … otherwise returns 52.
That is, YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52
Define “week”
You need to define a week. In your code sample, the definition of week varies by the JVM’s current default Locale. So your results may vary at runtime.
Your code also uses terrible date-time classes that were supplanted years ago by the modern java.time classes. Stop using GregorianCalendar & Calendar; they were replaced for good reasons.
ISO 8601 week
The ISO 8601 standard defines a week as:
Weeks start on Monday, end on Sunday.
Week # 1 has the first Thursday of the calendar-year.
That definition means:
The first and last few days of a week-based-year may be the trailing/leading days of the previous/following calendar-year.
The week-based-year has either 52 or 53 complete weeks.
If your definition differs, see the Answer by Ole V.V..
YearWeek:is53WeekYear
If this matches your definition, then add the ThreeTen-Extra library to your project to extend the java.time functionality built into Java 8 and later. You then have access to the YearWeek class.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
YearWeek yearWeekNow = YearWeek.now( z ) ;
boolean is53WeekYear = yearWeekNow.is53WeekYear() ;
int weeksLong = yearWeekNow.is53WeekYear() ? 53 : 52 ;
To ask about a particular week-based-year, just arbitrarily pick any week of the year. For example, for the week-based year 2020 we ask for week # 1.
int weeksLong = YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52 ;
LocalDate weekStart = YearWeek.of( 2020 , 1 ).atDay( DayOfWeek.MONDAY ) ;
weeksLong = 53
weekStart = 2019-12-30
Notice how the first day of the week-based-year of 2020 is from the calendar-year 2019.
Using the Wikipedia definition here. A year has 53 weeks if 1st Jan is a Thursday, or 31st Dec is a Thursday, otherwise it has 52 weeks. This definition is equivalent to the one you used. I think this is a way easier condition to check for, as you don't need to check for leap years.
Using the Java 8 java.time APIs:
int year = 2020;
boolean is53weekYear = LocalDate.of(year, 1, 1).getDayOfWeek() == DayOfWeek.THURSDAY ||
LocalDate.of(year, 12, 31).getDayOfWeek() == DayOfWeek.THURSDAY;
int weekCount = is53weekYear ? 53 : 52;
The flexible solution
This should work for any week numbering scheme that can be represented in a WeekFields object.
public static int noOfWeeks(WeekFields wf, int year) {
LocalDate lastDayOfYear = YearMonth.of(year, Month.DECEMBER).atEndOfMonth();
if (lastDayOfYear.get(wf.weekBasedYear()) > year) { // belongs to following week year
return lastDayOfYear.minusWeeks(1).get(wf.weekOfWeekBasedYear());
}
else {
return lastDayOfYear.get(wf.weekOfWeekBasedYear());
}
}
The idea is to find the week number of the last week of the week based year. I try first with 31 December, but that may be in the first week of the following year. If so, I go one week back.
I have tested pretty thoroughly with WeekFields.ISO, not so much with other WeekFields objects, but as I said, I believe it works.
If you know for a fact that you will always need ISO 8601 weeks, I think you should go with one of the good answers by Sweeper and by Basil Bourque. I posted this in case you needed a more flexible solution that would work with other week numbering schemes too.
Use java.time
The code in your question is funny in that it imports classes both from Joda-Time and from java.time, yet uses the old Calendar and GregorianCalendar from Java 1.1. These classes were poorly designed and are now long outdated, you should not use them. Joda-Time is in maintenance mode, java.time has taken over after it. Which is what I use and recommend that you use.
I think this should work just fine as well:
int year = 2020;
long numOfWeeks = LocalDate.of(year, 1, 1).datesUntil(LocalDate.of(year, 12, 31), Period.ofDays(7)).count();
System.out.println("Weeks: " + numOfWeeks);
Below code works for me.
public static int getTotalWeeksInYear(int year){
int totalWeeks=0;
Calendar calendar=Calendar.getInstance();
for(int month=0;month<12;mmonth++){
int day=1;
do{
calendar.set(year, month, day);
if(calendar.get(Calendar.DAY_OF_WEEK)==5)
totalWeeks++;
day++;
}while (day <=calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
}
return totalWeeks;
}
Using Java.time
public static long getTotalWeekByLocalDate(LocalDate ldate) {
long weeksInYear = IsoFields.WEEK_OF_WEEK_BASED_YEAR.rangeRefinedBy(ldate).getMaximum();
return weeksInYear;
}
After trying a lot in java 8. I could not find a solution. then I prepared Joda date and time dependency. It gave me a good answer as I expected
code:
for (int i = 2020; i < 2100; i++) {
int weeks = new DateTime().withYear(i).weekOfWeekyear().getMaximumValue();
System.out.println(i + " years : " + weeks);
}
Maven Dependency:
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.5</version>
</dependency>
I want to get Monday date from given week and year using Java 8 package java.time.
But at some point I am facing issue as it's not returning proper date.
private LocalDate getDateFromWeekAndYear(final String week,final String year){
LocalDate date = LocalDate.now();
date = date.with(WeekFields.ISO.dayOfWeek(), 1);
date = date.with(WeekFields.ISO.weekOfWeekBasedYear(), Long.parseLong(week));
date = date.with(WeekFields.ISO.weekBasedYear(), Long.parseLong(year));
return date;
}
For example:
If I pass week=1 and year=2013 then date is : 2012-12-31.
But if I pass week=53 and year=2015 then date is : 2014-12-29. I expected 2014-12-28.
Is there any logical mistake I am making or some other issue ?
This is astonishingly more difficult than the partially invalid expectations of OP and most answers show.
First to say: It is very important to define the correct order of week-based-manipulations. The OP has first applied day-manipulation, then year-based manipulation. The correct approach is in reverse! I will show the right helper method implementation:
public static void main(String... args) {
System.out.println(
getDateFromWeekAndYear("53", "2015")); // 2015-12-28, NOT 2014-12-28
System.out.println(
getDateFromWeekAndYear("53", "2015").get(WeekFields.ISO.weekOfWeekBasedYear())); // 53
System.out.println(
getDateFromWeekAndYear("53", "2014")); // 2014-12-29
System.out.println(
getDateFromWeekAndYear("53", "2014").get(WeekFields.ISO.weekOfWeekBasedYear())); // 1
}
private static LocalDate getDateFromWeekAndYear(final String week,final String year) {
int y = Integer.parseInt(year);
LocalDate date = LocalDate.of(y, 7, 1); // safer than choosing current date
// date = date.with(WeekFields.ISO.weekBasedYear(), y); // no longer necessary
date = date.with(WeekFields.ISO.weekOfWeekBasedYear(), Long.parseLong(week));
date = date.with(WeekFields.ISO.dayOfWeek(), 1);
return date;
}
If you don't respect this specific order then you will indeed get sometimes a 2014-date for the input 2015-W53 (depending on the current date).
Second problem: I have also avoided to start with current date in order to be not near start or end of calendar year (calendar year != week-based-year) and instead chosen midth of year as starting point.
The third problem is lenient handling of week 53 in (week-based)-year 2014. It does not exist because 2014 had only 52 weeks!!! A strict algorithm should recognize and reject such an input. Therefore I advise against using YearWeek.of(2014, 53) (in the external library Threeten-Extra) resulting in the first week of 2015, see also its javadoc. Better than such lenient handling would have been
YearWeek yw = YearWeek.of(2014, 52);
if (yw.is53WeekYear()) {
yw = YearWeek.of(2014, 53);
}
or using this code from my own time library Time4J (whose class CalendarWeek has extra i18n-features and extra week arithmetic in comparison with YearWeek):
CalendarWeek.of(2014, 53); // throws an exception
System.out.println(CalendarWeek.of(2014, 1).withLastWeekOfYear()); // 2014-W52
Only using java.time-package:
Using such external libraries would at least have helped to solve the first problem in a transparent way. If you are not willing to add an extra dependency then you can do this to handle week 53 if invalid:
If the expression WeekFields.ISO.weekOfWeekBasedYear() applied on the result of your helper method yields the value 1 then you know that week 53 was invalid. And then you can decide if you want to accept lenient handling or to throw an exception. But silent adjusting such an invalid input is IMHO bad design.
First, you need to calculate the first Monday of the first week of the year,
then simply plus multi of 7 to the date.
public static LocalDate firstMonday(int week, int year) {
LocalDate firstMonOfFirstWeek = LocalDate.now()
.with(IsoFields.WEEK_BASED_YEAR, year) // year
.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 1) // First week of the year
.with(ChronoField.DAY_OF_WEEK, 1); // Monday
// Plus multi of 7
return firstMonOfFirstWeek.plusDays( (week - 1) * 7);
}
public static void main(String[] args) {
System.out.println(firstMonday(1, 2013)); // 2012-12-31
System.out.println(firstMonday(53 ,2015 )); // 2015-12-28
}
tl;dr
YearWeek.of ( 2013 , 1 ).atDay ( DayOfWeek.MONDAY )
Incorrect expectations
Your expectations are not correct. The Monday of 2015-W53 is 2015-12-28, not 2014-12-28, year 2015 rather than 2014. There is no reason to expect 2014. Please edit your Question to explain your thoughts, if you need more explanation.
You may be confused about a calendar-year versus a week-based year. In the ISO 8601 definition of a week based year, week number one contains the first Thursday of the calendar-year. This means we have some overlap between the years. The last few days of a calendar-year may reside in the following week-based-year. And vice-versa, the first few days of a calendar-year may reside in the previous week-based-year.
As an example, you can see in the screenshot below, the last day of calendar 2012 (December 31) falls in week one of the following week-based-year of 2013 at week number 1. And in the other screen shot, we have the opposite, where the first three days of calendar 2016 (January 1, 2, & 3) land in the week-based-year of 2015 at week number 53.
The Monday of 2013-W01 is 2012-12-31.
The Monday of 2015-W53 is 2015-12-28.
YearWeek
I suggest adding the ThreeTen-Extra library to your project to make use of of the YearWeek class. Rather than pass around mere integer numbers for year and week, pass around objects of this class. Doing so makes your code more self-documenting, provides type-safety, and ensures valid values.
// Pass ( week-based-year-number, week-number ). *Not* calendar year! See the ISO 8601 standard.
YearWeek yw = YearWeek.of( 2013 , 1 );
You can pull any day from that week.
LocalDate ld = yw.atDay( DayOfWeek.MONDAY );
Let's try this kind of code.
YearWeek yw1 = YearWeek.of ( 2013 , 1 );
LocalDate ld1 = yw1.atDay ( DayOfWeek.MONDAY );
YearWeek yw2 = YearWeek.of ( 2015 , 53 );
LocalDate ld2 = yw2.atDay ( DayOfWeek.MONDAY );
System.out.println ( "yw1: " + yw1 + " Monday: " + ld1 );
System.out.println ( "yw2: " + yw2 + " Monday: " + ld2 );
yw1: 2013-W01 Monday: 2012-12-31
yw2: 2015-W53 Monday: 2015-12-28
Tip: To see those ISO 8601 standard week numbers on a Mac in Calendar.app, set System Preferences > Language & Region > Calendar > ISO 8601. Then in Calendar.app, set Preferences > Advanced > Show week numbers.
I wanted Monday of a week about 6 month ago - to be specific 26 weeks ago.. below code gave me the required date:
LocalDate.now().minusWeeks(26).with(WeekFields.ISO.dayOfWeek(), DayOfWeek.MONDAY.getValue())
I have a date in dd/mm (15/07) format, I need to add a single day to this date, so it becomes 16/07.
How can I do this in the easiest way in java?
You can use Calendar.
String dt = "15-07-2016";
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
Calendar c = Calendar.getInstance();
c.setTime(sdf.parse(dt));
c.add(Calendar.DATE, 1); // number of days to add
dt = sdf.format(c.getTime());
You can do this:
public String addDay(String date) {
String[] dateSplit = date.split("/");
String day = "" + (Integer.parseInt(dateSplit[0]) + 1);
return day + "/" + dateSplit[1];
}
But this isn't really a nice solution, because this doesn't handle month or year swaps (This you can add by yourself using the % operator)
Or you use the SimpleDateFormat like here: How can I increment a date by one day in Java?
java.time
The Answer by Goel is correct but outmoded.
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
MonthDay
The java.time classes include the MonthDay class to represent a month+day without year and without time zone.
String input = "15/07";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "dd/MM" );
MonthDay monthDay = MonthDay.parse( input , formatter );
Cannot increment February 28
As commented by Tom, you cannot reliably increment February 28. In most years you would get March 1 but in leap years you get February 29. This is why the YearMonth class lacks any addDays method.
So you need to (a) assume/supply a year, (b) refuse to increment the one day of February 28, or (c) arbitrarily increment to March 1 from February 28 to ignore any possible 29th.
Let's look at the first option, supplying a year.
To get the current year we need the current date. To get the current date, specify a time zone. For any given moment, the date varies around the globe by zone.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( zoneId );
int year = today.getYear();
We can apply that year number to change our YearMonth into a LocalDate. From there the LocalDate::plusDays method increments to the next day. From the resulting instance of LocalDate we extract a YearMonth object.
LocalDate ld = monthYear.atYear( year );
LocalDate nextDay = ld.plusDays( 1 );
YearMonth ymNextDay = MonthDay.from( nextDay );
I am trying to get the date of Monday or Thurday in this format YYYYMMDD
For Monday it should give me this - 20130224 (as an example)
For Thursday it should give me this - 20130227 (as an example)
Now, if I am running my program after Thursday or on Thursday, it should print date for Thursday in this format YYYYMMDD which can be 20130227 (coming thursday in this week).
And If I am running my program after Monday or on Monday, then it should print date for Monday in the same format YYYYMMMDD which can be 20130224 (yesterday Monday date as an example)
How would I do this in Java?
Below is what I have tried -
Calendar cal = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("EEE");
String text = formatter.format(cal.getTime());
System.out.println(text);
// but how do I check if it is Tuesday but less than Thursday
if(text.equalsIgnoreCase("Tue")) {
// get previous Monday date in YYYYMMDD
}
// and how do I check if it is thursday or greater than Thursday?
else if(text.equalsIgnoreCase("Thur")) {
// get previous Thursday date in YYYYMMDD
}
Update:-
In a particular week, if I am running my program on Thursday or after Thursday then it should return me date for Thursday in the same week in YYYYMMDD format, but if I am running my program on Monday or after Monday, then it should return me date for Monday in the same week in YYYYMMDD format.
For example, In this week, if I am running my program on Thursday or after Thursday, then it should return date for Thursday. But if I am running my program on Monday or Tuesday or Wednesday in this same week, then it should return me date for Monday.
Code:-
Below is my code -
public static void main(String[] args) {
try {
Calendar cal = Calendar.getInstance();
SimpleDateFormat toDateFormat = new SimpleDateFormat("yyyyMMdd");
int dow = cal.get(Calendar.DAY_OF_WEEK);
switch (dow) {
case Calendar.THURSDAY:
case Calendar.FRIDAY:
case Calendar.SATURDAY:
case Calendar.SUNDAY:
while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.THURSDAY) {
cal.add(Calendar.DATE, -1);
}
break;
case Calendar.MONDAY:
case Calendar.TUESDAY:
case Calendar.WEDNESDAY:
while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
cal.add(Calendar.DATE, -1);
}
break;
}
System.out.println(date);
System.out.println(cal.getTime());
System.out.println(toDateFormat.format(cal.getTime()));
} catch (ParseException exp) {
exp.printStackTrace();
}
}
Start by parsing the text value to a Date value...
String dateText = "20130224";
SimpleDateFormat toDateFormat = new SimpleDateFormat("yyyyMMdd");
Date date = toDateFormat.parse(dateText);
This gives you the starting point. Next you need to use a Calendar which will allow you move backwards and forwards, automatically rolling the date internally for you (so if you roll over week, month or year boundaries)
For example...
try {
String dateText = "20130227";
SimpleDateFormat toDateFormat = new SimpleDateFormat("yyyyMMdd");
Date date = toDateFormat.parse(dateText);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int dow = cal.get(Calendar.DAY_OF_WEEK);
switch (dow) {
case Calendar.THURSDAY:
case Calendar.FRIDAY:
case Calendar.SATURDAY:
case Calendar.SUNDAY:
while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.THURSDAY) {
cal.add(Calendar.DATE, -1);
}
break;
case Calendar.MONDAY:
case Calendar.TUESDAY:
case Calendar.WEDNESDAY:
while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
cal.add(Calendar.DATE, -1);
}
break;
}
System.out.println(date);
System.out.println(cal.getTime());
} catch (ParseException exp) {
exp.printStackTrace();
}
So, based on this example, it would output...
Wed Feb 27 00:00:00 EST 2013
Mon Feb 25 00:00:00 EST 2013
For 20130224 (which is a Sunday) it will give
Sun Feb 24 00:00:00 EST 2013
Thu Feb 21 00:00:00 EST 2013
I should also add, there's probably a much easier way to do this with JodaTime, but this is what I was able to wipe up quickly. Yes, I know the case statement is little winded, but SUNDAY is equal to 0, which is a little annoying ;)
What? Moving to a new question with the same contents?
String[] weeks = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
DateFormat df = new SimpleDateFormat("yyyyMMdd");
Calendar c = Calendar.getInstance();
c.setTime(new Date()); // Now use today date.
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK); // Sun=1, Mon=2, ... Sat=7
System.out.println("Today " + df.format(c.getTime()) + " is " + weeks[dayOfWeek-1]);
c.add(Calendar.DATE, 7); // Adding 7 days
System.out.println("Next " + weeks[dayOfWeek-1] + " is " + df.format(c.getTime()));
// Should display:
// Today 20140225 is Tuesday
// Next Tuesday is 20140304
I would use the calendar class day to get the day of the week. Calendar.DAY_OF_WEEK function returns 1 - 7 for Sunday - Saturday. This way you can do numeric comparison and not mess around with comparing the strings for the weekdays (which would be a mess if your app needs to support multiple languages).
See:
http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html
If I understood what you're after, then this should work
private static final java.text.SimpleDateFormat sdf =
new java.text.SimpleDateFormat("yyyyMMdd");
public static String calculateCorrectDate(
java.util.Date d) {
java.util.Calendar cal = java.util.Calendar
.getInstance();
cal.setTime(d);
int dayOfWeek = cal
.get(java.util.Calendar.DAY_OF_WEEK);
if (dayOfWeek >= java.util.Calendar.MONDAY
&& dayOfWeek < java.util.Calendar.THURSDAY) {
cal.set(java.util.Calendar.DAY_OF_WEEK,
java.util.Calendar.MONDAY);
} else {
cal.set(java.util.Calendar.DAY_OF_WEEK,
java.util.Calendar.THURSDAY);
}
return sdf.format(cal.getTime());
}
public static void main(String[] args) {
java.util.List<java.util.Date> dates = new java.util.ArrayList<java.util.Date>();
java.util.Calendar cal = java.util.Calendar
.getInstance();
String today = sdf.format(cal.getTime());
cal.add(java.util.Calendar.DAY_OF_WEEK, -10);
for (int i = 0; i < 20; i++) {
dates.add(cal.getTime());
cal.add(java.util.Calendar.DAY_OF_WEEK, 1);
}
for (java.util.Date d : dates) {
if (sdf.format(d).equals(today)) {
System.out.println("TODAY!");
}
System.out.println(calculateCorrectDate(d));
}
}
Which gives the output
20140213
20140220
20140217
20140217
20140217
20140220
20140220
20140220
20140227
20140224
TODAY!
20140224
20140224
20140227
20140227
20140227
20140306
20140303
20140303
20140303
20140306
or with a few import(s),
// Import Static
// This simplifies accessing the Calendar fields. Use sparingly.
import static java.util.Calendar.DAY_OF_WEEK;
import static java.util.Calendar.MONDAY;
import static java.util.Calendar.THURSDAY;
// The other imports.
import java.util.Calendar;
import java.util.Date;
Then you can use,
public static String calculateCorrectDate(Date d) {
Calendar cal = Calendar.getInstance();
cal.setTime(d);
// By using import static this remains concise and correct.
int dayOfWeek = cal.get(DAY_OF_WEEK);
if (dayOfWeek >= MONDAY && dayOfWeek < THURSDAY) {
cal.set(DAY_OF_WEEK, MONDAY);
} else {
cal.set(DAY_OF_WEEK, THURSDAY);
}
return sdf.format(cal.getTime());
}
Joda-Time
UPDATE: The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. This Answer is left intact as history. See my modern Answer instead.
Yes, Joda-Time is the solution.
Or the new java.time package in Java 8. Inspired by Joda-Time but re-architected. Defined by JSR 310.
Next Monday/Thursday
Search StackOverflow for getting first or last day of week. That will show you how to get next monday or thursday. I won't cover that part of your question here.
Testing Day Of Week
Testing for the day of week by the English word is prone to break if you ever happen to run where English is not the default locale. Instead, get day of week by number. Joda-Time uses ISO 8601 as its defaults, so Monday = 1, Sunday = 7. Constants are provided, so you needn't memorize the numbers.
Date Without Time
If you truly don't care about time-of-day, only date, then we can use LocalDate rather than DateTime.
Example Code
Some code to get you started, using Joda-Time 2.3.
String input = "20130224";
DateTimeFormatter formatterInput = DateTimeFormat.forPattern( "yyyyMMdd" );
LocalDate localDate = formatterInput.parseLocalDate( input );
int dayOfWeek = localDate.getDayOfWeek();
boolean isMonday = ( localDate.getDayOfWeek() == DateTimeConstants.MONDAY );
boolean isThursday = ( localDate.getDayOfWeek() == DateTimeConstants.THURSDAY );
Dump to console…
System.out.println( "localDate: " + localDate );
System.out.println( "dayOfWeek: " + dayOfWeek );
System.out.println( "isMonday: " + isMonday );
System.out.println( "isThursday: " + isThursday );
When run…
localDate: 2013-02-24
dayOfWeek: 7
isMonday: false
isThursday: false
tl;dr
If:
EnumSet.range( DayOfWeek.MONDAY , DayOfWeek.WEDNESDAY ) // Monday, Tuesday, & Wednesday.
contains( LocalDate.now().getDayOfWeek() ) // If today’s date is a day-of-week that happens to be a member of that `Set`.
…then, apply:
TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) // Adjust into an earlier `LocalDate` that is a Monday, unless today already is Monday.
…else apply:
TemporalAdjusters.previousOrSame( DayOfWeek.THURSDAY ) // Otherwise move to a Thursday.
java.time
The modern approach uses the java.time classes. So much easier to solve this Question.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
DayOfWeek enum
The DayOfWeek enum defines a set of seven objects, one for each day of the week.
An EnumSet is a highly-optimized implementation of Set for collecting enum objects. So we can make a pair of EnumSet objects to hold a collection of DayOfWeek objects to define your two conditions: (Monday & Tuesday) versus (Thursday…Sunday).
Despite mysteriously failing to implement SortedSet, an EnumSet is indeed sorted in the natural order (declared order) of the enum. For DayOfWeek that would be Monday-Sunday, numbered 1-7 though you may never need those numbers.
Set < DayOfWeek > mondayDays = EnumSet.range( DayOfWeek.MONDAY , DayOfWeek.WEDNESDAY ); // Monday, Tuesday, & Wednesday.
Set < DayOfWeek > thursdayDays = EnumSet.range( DayOfWeek.THURSDAY , DayOfWeek.SUNDAY ); // Thursday, Friday, Saturday, Sunday.
Get the day-of-week for our source date. Prepare to match that against our enum sets.
LocalDate ld = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ) ; // Get today’s current date in a particular time zone.
DayOfWeek dow = ld.getDayOfWeek();
LocalDate target = LocalDate.EPOCH; // Or null. The `LocalDate.EPOCH` is first moment of 1970 in UTC, 1970-01-01T00:00:00Z.
See which Set has the day-of-week of our date. From there, adjust into a previous or same date for the desired day-of-week (Monday or Thursday).
if ( mondayDays.contains( dow ) )
{
target = ld.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) );
} else if ( thursdayDays.contains( dow ) )
{
target = ld.with( TemporalAdjusters.previousOrSame( DayOfWeek.THURSDAY ) );
} else
{
System.out.println( "ERROR - Unexpectedly reached IF-ELSE. " );
}
Generate string in your desired format. Your chosen format happens to be the “basic” version of standard ISO 8601 format where the use of delimiters is minimized.
String output = target.format( DateTimeFormatter.BASIC_ISO_DATE ) ; // YYYY-MM-DD
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
hi i want to make a program in java where days,weekNo is parameter ..Like First Friday of the month or second Monday of the month ..and it returns the date
Here's a utility method that does that, using DateUtils from Apache Commons / Lang:
/**
* Get the n-th x-day of the month in which the specified date lies.
* #param input the specified date
* #param weeks 1-based offset (e.g. 1 means 1st week)
* #param targetWeekDay (the weekday we're looking for, e.g. Calendar.MONDAY
* #return the target date
*/
public static Date getNthXdayInMonth(final Date input,
final int weeks,
final int targetWeekDay){
// strip all date fields below month
final Date startOfMonth = DateUtils.truncate(input, Calendar.MONTH);
final Calendar cal = Calendar.getInstance();
cal.setTime(startOfMonth);
final int weekDay = cal.get(Calendar.DAY_OF_WEEK);
final int modifier = (weeks - 1) * 7 + (targetWeekDay - weekDay);
return modifier > 0
? DateUtils.addDays(startOfMonth, modifier)
: startOfMonth;
}
Test code:
// Get this month's third thursday
System.out.println(getNthXdayInMonth(new Date(), 3, Calendar.THURSDAY));
// Get next month's second wednesday:
System.out.println(getNthXdayInMonth(DateUtils.addMonths(new Date(), 1),
2,
Calendar.WEDNESDAY)
);
Output:
Thu Nov 18 00:00:00 CET 2010
Wed Dec 08 00:00:00 CET 2010
And here's a JodaTime version of the same code (I've never used JodaTime before, so there's probably a simpler way to do it):
/**
* Get the n-th x-day of the month in which the specified date lies.
*
* #param input
* the specified date
* #param weeks
* 1-based offset (e.g. 1 means 1st week)
* #param targetWeekDay
* (the weekday we're looking for, e.g. DateTimeConstants.MONDAY
* #return the target date
*/
public static DateTime getNthXdayInMonthUsingJodaTime(final DateTime input,
final int weeks,
final int targetWeekDay){
final DateTime startOfMonth =
input.withDayOfMonth(1).withMillisOfDay(0);
final int weekDay = startOfMonth.getDayOfWeek();
final int modifier = (weeks - 1) * 7 + (targetWeekDay - weekDay);
return modifier > 0 ? startOfMonth.plusDays(modifier) : startOfMonth;
}
Test Code:
// Get this month's third thursday
System.out.println(getNthXdayInMonthUsingJodaTime(new DateTime(),
3,
DateTimeConstants.THURSDAY));
// Get next month's second wednesday:
System.out.println(getNthXdayInMonthUsingJodaTime(new DateTime().plusMonths(1),
2,
DateTimeConstants.WEDNESDAY));
Output:
2010-11-18T00:00:00.000+01:00
2010-12-08T00:00:00.000+01:00
public static Date getDate(int day, int weekNo, int month, int year) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DATE,1);
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
for (int i = 0; i < 31; i++) {
if (cal.get(Calendar.WEEK_OF_MONTH) == weekNo
&& cal.get(Calendar.DAY_OF_WEEK) == day) {
return cal.getTime();
}
cal.add(Calendar.DATE,1);
}
return null;
}
Calling code
System.out.println(""+getDate(Calendar.MONDAY, 2, Calendar.DECEMBER,2010));
Output
Mon Dec 06 15:09:00 IST 2010
Resource
Also look at Joda Time it is better
tl;dr
LocalDate firstFridayThisMonth =
LocalDate.now( ZoneId.of( "America/Montreal" ) )
.with( TemporalAdjusters.firstInMonth( DayOfWeek.FRIDAY ) )
Using java.time
The other Answers are now outdated. The troublesome old date-time classes (Date, Calendar, etc.) are now legacy, supplanted by the java.time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
TemporalAdjuster
The TemporalAdjuster interface provides for manipulating date-time values. The java.time classes use immutable objects, so the result is always a fresh new object with values based on the original.
The TemporalAdjusters class (note plural name) provides several handy implementations. Amongst those are ones to get ordinal day-of-week within the month: firstInMonth(), lastInMonth(), and dayOfWeekInMonth(). All of these take an argument of a DayOfWeek enum object.
LocalDate firstFridayOfThisMonth =
today.with(
TemporalAdjusters.firstInMonth( DayOfWeek.FRIDAY )
)
;
…and…
LocalDate secondMondayOfThisMonth =
today.with(
TemporalAdjusters.dayOfWeekInMonth( 2 , DayOfWeek.MONDAY )
)
;
…and…
LocalDate thirdWednesdayOfNextMonth =
today.plusMonths( 1 )
.with(
TemporalAdjusters.dayOfWeekInMonth( 3 , DayOfWeek.WEDNESDAY )
)
;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Calendar cal = Calendar.getInstance();
int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
this should do what you want.
edit:
with some more calculate steps, you could have result :) (sorry for confuse your title)