I was looking for a way to make optimum of Java 8's LocalDate to find next year's date which falls on same day of week.
For example today is 1rd March 2022 - Tuesday. Assume this is the input date, the the output date that I expect to get is 28th Feb 2023, because its the same day (Tuesday) for next year
One option that I tried was adding 364 days as shown in the example
public static void main(String args[]){
LocalDate currentDate= LocalDate.now();
System.out.println("Current Date: " + currentDate + " Day" currentDate.getDayOfWeek().name());
System.out.println("Next Year's date: " + currentDate.plusDays(364) + " Next year day: " +currentDate.plusDays(364).getDayOfWeek().name());
}
This works but may have drawback with leap years.
Other option is to add 1 year to current date and do a while loop check for dayOfWeek for each day - 1
Is there a better way to do this?
Related
I want to retrieve same day previous year.
e.g. today is 2019-03-30 that is year 2019, week 26(week of year), day 7 (day of week).
I need to construct LocalDate which is year 2018, week 26(week of year), day 7 (day of week).
I could not find from java.time package which can built LocalDate like this.
It seems like you want the previous year date with same week of year and day of week as the given date. Below code with give you that result.
LocalDate currentLocalDate = LocalDate.now();
int dayOfWeek = currentLocalDate.getDayOfWeek().getValue();
int weekOfYear = currentLocalDate.get(ChronoField.ALIGNED_WEEK_OF_YEAR);
LocalDate resultLocalDate = currentLocalDate
.minusYears(1)
.with(ChronoField.ALIGNED_WEEK_OF_YEAR, weekOfYear)
.with(ChronoField.DAY_OF_WEEK, dayOfWeek);
Full Example (live copy):
import java.time.*;
import java.time.format.*;
import java.time.temporal.*;
class Example
{
private static void showDateInfo(LocalDate ld) {
int weekOfYear = ld.get(ChronoField.ALIGNED_WEEK_OF_YEAR);
int dayOfWeek = ld.getDayOfWeek().getValue();
System.out.println(ld.format(DateTimeFormatter.ISO_LOCAL_DATE) + " is week " + weekOfYear + ", day " + dayOfWeek);
}
public static void main (String[] args) throws java.lang.Exception
{
LocalDate currentLocalDate = LocalDate.of(2019, 6, 30);
showDateInfo(currentLocalDate);
int dayOfWeek = currentLocalDate.getDayOfWeek().getValue();
int weekOfYear = currentLocalDate.get(ChronoField.ALIGNED_WEEK_OF_YEAR);
LocalDate resultLocalDate = currentLocalDate
.minusYears(1)
.with(ChronoField.ALIGNED_WEEK_OF_YEAR, weekOfYear)
.with(ChronoField.DAY_OF_WEEK, dayOfWeek);
showDateInfo(resultLocalDate);
}
}
Output:
2019-06-30 is week 26, day 7
2018-07-01 is week 26, day 7
I believe that the other answers are close but not quite there yet. As far as I understand, you want to use the week scheme of the default locale, which the other answers don’t do. My suggestion is:
WeekFields wf = WeekFields.of(Locale.getDefault());
LocalDate today = LocalDate.now(ZoneId.of("Africa/Casablanca"));
int week = today.get(wf.weekOfYear());
int dow = today.get(wf.dayOfWeek());
System.out.println("Today is " + today + ", "
+ today.getDayOfWeek() + " of week " + week);
LocalDate correspondingDayLastYear = today.minusYears(1)
.with(wf.weekOfYear(), week)
.with(wf.dayOfWeek(), dow);
System.out.println("Last year was " + correspondingDayLastYear + ", "
+ correspondingDayLastYear.getDayOfWeek()
+ " of week " + correspondingDayLastYear.get(wf.weekOfYear()));
When running on my computer just now the output was:
Today is 2019-06-30, SUNDAY of week 26
Last year was 2018-07-01, SUNDAY of week 26
When I set my locale to US I get the same date, but a different week number since American weeks are defined differently:
Today is 2019-06-30, SUNDAY of week 27
Last year was 2018-07-01, SUNDAY of week 27
I believe that there will also be cases where different locales will give you different dates.
wf.dayOfWeek() gives you a field that numbers the days from 1 to 7 according to the first day of week in that particular locale. It’s important not just to use withDayOfWeek or equivalent, or you would risk sliding into a different week if not using ISO weeks.
Still my answer will not work always! If today is within week 53 of the year, it may very well be that last year didn’t have a week 53. Not much we can do about that. Another problem we can’t solve: In American weeks week 1 starts on January 1. If this is a Sunday, it is the first day for the week, but then week 1 of the previous year started on a Friday or Saturday, so week 1 didn’t have any Sunday.
If you're looking for an ISO week-year compatible function, this is working for me - so far =].
public class FiscalDateUtil {
private static Logger log = LoggerFactory.getLogger(FiscalDateUtil.class);
static public LocalDate previousYearComparisonDate(LocalDate date) {
final int weekYear = date.get(IsoFields.WEEK_BASED_YEAR);
final int weekLastYear = weekYear-1;
final DayOfWeek dayOfWeek = date.getDayOfWeek();
final int weekOfYear = date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
final LocalDate adjustedLastYear = date
.with(IsoFields.WEEK_BASED_YEAR, weekLastYear)
.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekOfYear)
.with(TemporalAdjusters.nextOrSame(dayOfWeek));
if (log.isTraceEnabled()) {
log.trace("starting date {}", date.toString());
log.trace("starting date dow {}", date.getDayOfWeek());
log.trace("lastYear {}", weekLastYear);
log.trace("lastYear dow {}", dayOfWeek);
log.trace("adjustedLastYear {}", adjustedLastYear.toString());
log.trace("adjustedLastYear dow {}", adjustedLastYear.getDayOfWeek());
}
return adjustedLastYear;
}
}
You can add the number of days since beginning of year of the current date to the beginning of the year before.
This should do the trick:
String dateStr = "2019-03-30";
LocalDate date = LocalDate.parse(dateStr);
LocalDate newDate = LocalDate.parse(date.getYear() + "-01-01").plusDays(date.getDayOfYear());
System.out.println(newDate);
I have a problem when I try use Calendar.
Look:
public static Calendar novaData(Calendar originDate, Integer amountMonth) {
System.out.println("Origin date: " + originDate.getTime() + " - Add " + amountMonth + " Months");
Calendar date = new GregorianCalendar(originDate.getTimeZone());
date.add(Calendar.MONTH, amountMonth);
System.out.println(date.getTime());
return date;
}
Now, the console:
In this method, I'll set a date and the amount of month I'm going to add to that date. The problem is there and the day is coming like today (18) and not day 1 as I passed. The expected result is May / 01/2019 - Jun / 01/2019 - Jul / 01/2019
java.time
LocalDate originDate = LocalDate.of(2019, Month.MAY, 1);
for (int amountMonth = 1; amountMonth <= 3; amountMonth++) {
System.out.println("Origin date: " + originDate + " - Add " + amountMonth + " Months");
System.out.println(originDate.plusMonths(amountMonth));
}
Output is:
Origin date: 2019-05-01 - Add 1 Months
2019-06-01
Origin date: 2019-05-01 - Add 2 Months
2019-07-01
Origin date: 2019-05-01 - Add 3 Months
2019-08-01
I gather from your desired output that you are only interested in the date, not the time of day nor the time zone. If so, the LocalDate class is the correct class to use.
If you are only interested in the month, not the day of month, use YearMonth instead of LocalDate. The code will be the same except for the declaration and initialization:
YearMonth originDate = YearMonth.of(2019, Month.MAY);
Origin date: 2019-05 - Add 1 Months
2019-06
(etc.)
Don’t use Calendar and GregorianCalendar. Those classes are poorly designed and long outdated. On top of that they carry with each object a time of day, a time zone, a week scheme and more, all of which I don’t think you need and that will only risk confusing those that read your code.
Link: Oracle tutorial: Date Time explaining how to use java.time.
First, if at all possible consider using the newer Java Date objects. See, e.g., this blog.
However, the specific issue of the OP is that the new GregorianCalendar call will create based upon the current date/time of the user. It is not using the specified date/time of the originDate.
One way to adjust the code would be:
public static Calendar novaData(Calendar originDate, Integer amountMonth) {
System.out.println("Origin date: " + originDate.getTime() + " - Add " + amountMonth + " Months");
Calendar date = new GregorianCalendar();
date.setTime(originDate.getTime());
date.setTimeZone(originDate.getTimeZone());
date.add(Calendar.MONTH, amountMonth);
System.out.println(date.getTime());
return date;
}
Based upon the test input, the output moves the month forward. See it here
Origin date: Sat May 18 18:01:21 GMT 2019 - Add 0 Months
Sat May 18 18:01:21 GMT 2019
Origin date: Sat May 18 18:01:21 GMT 2019 - Add 1 Months
Tue Jun 18 18:01:21 GMT 2019
Origin date: Sat May 18 18:01:21 GMT 2019 - Add 2 Months
Thu Jul 18 18:01:21 GMT 2019
Please note that issues with leap years, negative amounts, etc. are not fully considered.
Plase have a look at the below code
Calendar date = Calendar.getInstance();
initialClientLetterDate.setText(date.get(Calendar.YEAR)+"/"+date.get(Calendar.MONTH)+"/"+date.get(Calendar.DAY_OF_WEEK));
This generates the invalid "month" and "date". The output is 2014/09/06. Why is this? I just wanted to get current year, date and month.
You are using DAY_OF_WEEK which is 6 for FRIDAYand MONTH starts from 0 not 1 so you have to add 1 in it.You can use DAY_OF_MONTH instead of DAY_OF_WEEK.
You can do like as below code. You should not forgot to set locale.
public static void main(String args[]) {
Calendar date = Calendar.getInstance(Locale.US);
System.out.println(date.get(Calendar.YEAR) + "/"
+ (date.get(Calendar.MONTH) + 1) + "/"
+ date.get(Calendar.DAY_OF_MONTH));
}
DAY_OF_WEEK Returns an int (starting at 1?) for the day in the week so Friday would be 6, Month does the same except starting at 0 so 09 would be October.
http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#DAY_OF_WEEK
date.get(Calendar.YEAR) = Gives the current year
date.get(Calendar.MONTH) = Gives the month of the year as an integer from 0 to 11, where 0 = Jan and 11 = dec
date.get(Calendar.DAY_OF_WEEK) = Gives the day of the week from 0 to 6, where 0 = Monday
So if you want to get the current date you must do
date.get(Calendar.YEAR)+"/"+(date.get(Calendar.MONTH)+1)+"/"+date.get(Calendar.DAY_OF_MONTH)
I want to get the date of the first monday of the current week and the first friday of the current week.
I tried it this way:
Calendar calendarFirstDay = Calendar.getInstance(Locale.GERMANY);
Calendar calendarLastDay = Calendar.getInstance(Locale.GERMANY);
Date now = new Date();
calendarFirstDay.setTime(now);
calendarLastDay.setTime(now);
calendarFirstDay.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
calendarLastDay.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
MyTextView.setText(calendarFirstDay.get(Calendar.DATE) + "." + calendarFirstDay.get(Calendar.MONTH) + "." + calendarFirstDay.get(Calendar.YEAR) + " - " + calendarLastDay.get(Calendar.DATE) + "." + calendarLastDay.get(Calendar.MONTH) + "." + calendarLastDay.get(Calendar.YEAR));
If I try this script today (Sunday, 26.1.2014), the output is the following:
20.0.2014 - 24.0.2014
Correct would be 20.1.2014 - 24.1.2014
Does somebody knows why my month is zero?
From the JavaDocs:
Field number for get and set indicating the month. This is a calendar-specific value. The first month of the year in the Gregorian and Julian calendars is JANUARY which is 0; the last depends on the number of months in a year.
Thus the first month (January) has a MONTH value of 0, and not 1 (as you'd expect).
There's a much better solution though: use a DateFormat or SimpleDateFormat to format dates as text. That way, you simply don't have to worry about this and let the DateFormat take care of it. For example:
DateFormat myFormat = new SimpleDateFormat("dd.MM.yyyy");
MyTextView.setText(
myFormat.format(calendarFirstDay.getTime()) + " - " +
myFormat.format(calendarLastDay.getTime())
);
As stated in
http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#set(int,%20int,%20int)
if you use this method, January will be 0 and Decmember will be 11, so you should just add 1 to your month.
EDIT: You are using the get method but it's probably 0-based, too.
I am developing an application in JAVA swing, in that I wanted the date difference from current date like if today is 16/04/2013 then it should return 15/04/2013. I have tried the following code:
Calendar cal = new GregorianCalendar();
Calendar cal2 = new GregorianCalendar();
cal.roll(Calendar.DAY_OF_YEAR, -1);
//if within the first 30 days, need to roll the year as well
if(cal.after(cal2)){
cal.roll(Calendar.YEAR, -1);
}
System.out.println("Year " + cal.get(Calendar.YEAR));
System.out.println("Month " + cal.get(Calendar.MONTH));
System.out.println("Day " + cal.get(Calendar.DAY_OF_MONTH));
In this code I was expecting to get one day back date. But instead I am getting one month back date.
Ex. if today is 16/04/2013, the expected output is 15/04/2013, but I am getting 15/03/2013 ( one month one day back) as an output.
You dont need any manual manipulations, Calendar will do all necessary date arithmetic automatically, simply do this
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DATE, -1);
Note that months in Calendar start from 0 so April is 3
That's a classic example why java.util.Date implementation sucks: Months numeration starts in zero:
0-> January
1-> February
2-> March
3-> April.
What you mean:
new Date(10,1,2013) //10th of January of 2013
What you get: 10th of February of 3983 (1970+2013)