Calendar returns wrong Week of the year - java

I want to get this current week on the day of 9/10/2018 as the 42 week of the year after setting the First Day of the week to Sunday. Still I get the output as 41 from the below snippet
Calendar c = Calendar.getInstance();
c.setFirstDayOfWeek(Calendar.SUNDAY);
System.out.println( c.get(Calendar.WEEK_OF_YEAR) );
Am I missing something here?
Background: Our week start can be variable. Our configuration has the ability to let users decide the first day of the week.

Sorry if I’m too persistent. I still think you should leave the calculation to a custom WeekFields object. If I understood your comment correctly, you want:
final int daysPerWeek = DayOfWeek.values().length; // A wordy way of writing 7 :-)
WeekFields customWeekFields = WeekFields.of(firstDayOfWeek, daysPerWeek);
int customWeekNumber = date.get(customWeekFields.weekOfWeekBasedYear());
To test whether this agrees with what you are already doing I wrote the following method:
static void printWeekNumber(DayOfWeek firstDayOfWeek, LocalDate date) {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("EEE uuuu-MM-dd", Locale.ENGLISH);
final int daysPerWeek = DayOfWeek.values().length;
// Week number according to your comment: “using the Temporal adjusters
// I am getting the date on the last day of the week.
// After that dividing the Day of the Year from the API by 7”
DayOfWeek lastDayOfWeek = firstDayOfWeek.minus(1);
int askersCommentWeekNumber = date
.with(TemporalAdjusters.nextOrSame(lastDayOfWeek))
.getDayOfYear()
/ daysPerWeek;
// My suggested way of calculating the same week number
WeekFields customWeekFields = WeekFields.of(firstDayOfWeek, daysPerWeek);
int customWeekNumber = date.get(customWeekFields.weekOfWeekBasedYear());
System.out.format(Locale.ENGLISH, "Week begins on %-8s Date is %s. Week %2d or %2d, agree? %s%n",
firstDayOfWeek, date.format(dateFormatter),
askersCommentWeekNumber, customWeekNumber,
askersCommentWeekNumber == customWeekNumber);
}
To make it easier to check the calculations by hand, I have picked a date in January in different years:
printWeekNumber(DayOfWeek.SUNDAY, LocalDate.of(2017, Month.JANUARY, 9));
printWeekNumber(DayOfWeek.MONDAY, LocalDate.of(2017, Month.JANUARY, 9));
printWeekNumber(DayOfWeek.THURSDAY, LocalDate.of(2017, Month.JANUARY, 9));
printWeekNumber(DayOfWeek.SUNDAY, LocalDate.of(2018, Month.JANUARY, 9));
printWeekNumber(DayOfWeek.MONDAY, LocalDate.of(2018, Month.JANUARY, 9));
printWeekNumber(DayOfWeek.SUNDAY, LocalDate.of(2019, Month.JANUARY, 9));
printWeekNumber(DayOfWeek.MONDAY, LocalDate.of(2019, Month.JANUARY, 9));
Output:
Week begins on SUNDAY Date is Mon 2017-01-09. Week 2 or 2, agree? true
Week begins on MONDAY Date is Mon 2017-01-09. Week 2 or 2, agree? true
Week begins on THURSDAY Date is Mon 2017-01-09. Week 1 or 1, agree? true
Week begins on SUNDAY Date is Tue 2018-01-09. Week 1 or 1, agree? true
Week begins on MONDAY Date is Tue 2018-01-09. Week 2 or 2, agree? true
Week begins on SUNDAY Date is Wed 2019-01-09. Week 1 or 1, agree? true
Week begins on MONDAY Date is Wed 2019-01-09. Week 1 or 1, agree? true
Please check whether the results are as you want them, though. For the example in your question, the result is neither 41 nor 42:
printWeekNumber(DayOfWeek.SUNDAY, LocalDate.of(2018, Month.OCTOBER, 9));
Week begins on SUNDAY Date is Tue 2018-10-09. Week 40 or 40, agree? true
Edit: If you want ISO 8601 week numbers, use date.get(WeekFields.ISO.dayOfWeek()). If you want your custom first day of week and 4 days in the first week as in ISO 8601, use:
WeekFields customWeekFields = WeekFields.of(firstDayOfWeek, 4);

Related

Get start date of current financial year

Here in the UK, the tax year runs from 6 April to 5 April each year. I want to get the start date of the current tax year (as a LocalDate), so for example if today is 3 April 2020, then return 6 April 2019, and if today is 8 April 2020, then return 6 April 2020.
I can calculate it using some logic like the following:
date = a new LocalDate of 6 April with today's year
if (the date is after today) {
return date minus 1 year
} else {
return date
}
But is there some method I can use that is less complex and uses a more succinct, perhaps functional style?
There are a few different approaches, but it's easy enough to implement the logic you've already specified in a pretty functional style:
private static final MonthDay FINANCIAL_START = MonthDay.of(4, 6);
private static LocalDate getStartOfFinancialYear(LocalDate date) {
// Try "the same year as the date we've been given"
LocalDate candidate = date.with(FINANCIAL_START);
// If we haven't reached that yet, subtract a year. Otherwise, use it.
return candidate.isAfter(date) ? candidate.minusYears(1) : candidate;
}
That's pretty concise and simple. Note that it doesn't use the current date - it accepts a date instead. That makes it much easier to test. It's easy enough to call this and provide the current date, of course.
using java.util.Calendar, you can get financial year's START and END date in which your given date lies.
In India financial year starts from from 1 April and ends on 31st March,
for financial year 2020-21 , dates will be 1 April 2020
public static Date getFirstDateOfFinancialYear(Date dateToCheck) {
int year = getYear(dateToCheck);
Calendar cal = Calendar.getInstance();
cal.set(year, 3, 1); // 1 April of Year
Date firstAprilOfYear = cal.getTime();
if (dateToCheck.after(firstAprilOfYear)) {
return firstAprilOfYear;
} else {
cal.set(year - 1, 3, 1);
return cal.getTime();
}
}
In your case set cal.set(year, 0, 1); // 1 Jan of Year
public static Date getLastDateOfFinancialYear(Date dateToCheck) {
int year = getYear(dateToCheck);
Calendar cal = Calendar.getInstance();
cal.set(year, 2, 31); // 31 March of Year
Date thirtyFirstOfYear = cal.getTime();
if (dateToCheck.after(thirtyFirstOfYear)) {
cal.set(year + 1, 2, 31);
return cal.getTime();
} else {
return thirtyFirstOfYear;
}
}
In your case set cal.set(year, 11, 31); // 31 Dec of Year

Java Calendar bug when set date is 30/12 or 31/12 [duplicate]

This question already has answers here:
Y returns 2012 while y returns 2011 in SimpleDateFormat
(5 answers)
Java Date year calculation is off by year for two days
(5 answers)
Closed 3 years ago.
I use class Calendar to create Date. But in my test case when i set date is 31/12 or 30/12, year of my date is my set year of date + 1. Example 2018-12-29 -> 2018-12-29 but 2018-12-30 -> 2019-12-30. I don't know why ? My code:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class MyClass {
public static void main(String args[]) {
calendarBug(2018, 11, 29);
calendarBug(2018, 11, 30);
}
public static void calendarBug(int year, int month, int day) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, day);
Date date = calendar.getTime();
System.out.println(new SimpleDateFormat("YYYY-MM-dd").format(date));
}
}
Output:
2018-12-29
2019-12-30
YYYY represents for week year. Use yyyy instead.
From javadocs:
A week year is in sync with a WEEK_OF_YEAR cycle. All weeks between
the first and last weeks (inclusive) have the same week year value.
Therefore, the first and last days of a week year may have different
calendar year values.
For example, January 1, 1998 is a Thursday. If getFirstDayOfWeek() is
MONDAY and getMinimalDaysInFirstWeek() is 4 (ISO 8601 standard
compatible setting), then week 1 of 1998 starts on December 29, 1997,
and ends on January 4, 1998. The week year is 1998 for the last three
days of calendar year 1997. If, however, getFirstDayOfWeek() is
SUNDAY, then week 1 of 1998 starts on January 4, 1998, and ends on
January 10, 1998; the first three days of 1998 then are part of week
53 of 1997 and their week year is 1997.

Create LocalDate from Calendar Week Information

Given:
A Year: 2019
A Calender Week Number: 1 (== 1st Week of a year)
A DayOfWeek: SUNDAY
Needed:
A transformation f of those Infos into a LocalDate Object so that
assertEquals(LocalDate.of(2019,1,6), f(2019,1,SUNDAY))
What I tried
I did not find a way with java.time.* to create a Date from an Info like "The Sunday of the first calender week in 2019". I found that the old java.util.Calendar class had a setWeekDate() function that could be usefull. But the following code caused an Exception:
...
Calendar c = Calendar.getInstance();
c.setWeekDate(2019, 1, Calendar.MONDAY);
c.setTimeZone(TimeZone.getDefault());
return LocalDate.from(c.toInstant());
java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: 2018-01-08T20:03:55.602Z of type java.time.Instant
at java.time.LocalDate.from(LocalDate.java:379)
at ...
Check ChronoField or IsoFields for a suitable way to get week for the calendar system that you want to use. LocalDate object that is used as "base" value should have a week value of the expected year.
int year = 2019;
int weekNumber = 1;
LocalDate localDate = LocalDate.of(year, 2, 1)
.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber)
.with(ChronoField.DAY_OF_WEEK, DayOfWeek.SUNDAY.getValue());
Selecting first date is meaningful. Using LocalDate.of(year, 1, 1) would give a day that can belong to last week of the previous year, same goes for LocalDate.now()but only for given period of time.
LocalDate.of(2017, 1, 1)
.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 26)
.with(ChronoField.DAY_OF_WEEK, DayOfWeek.SUNDAY.getValue());
// 2016-07-03
LocalDate.of(2017, 1, 1).get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
// 52
So jumping from week 52 to week 26 would give date of 2016-07-03 because date is calculated by subtracking time between weeks 52 and 26.
Also see answer here for more discussion about withYear: Unexpected date calculation result

Java, easiest way to identify if one week away or one month etc using dates

After 20 minutes of coding my attempt which was,
if given dd/mm/year and I have my current dd/mm/year, if
the difference in years = 0, the difference in months = 0 and the difference in days = 7, then you're 1 week away.
Then I realized, this doesn't take into account date wrapping. For instance, if I'm given the date of 07/01/2017 and my current date is 06/29/2017. My algorithm would return false, but you're in fact less than 1 week away. (Depending on month as well, i.e. 30 or 31 days).
Therefore my question is, what is the easiest way to check if you're either:
1 month, two weeks or 1 week away from a date when
Given the date and
I am using the time given from LocalDateTime.now()
Here is an example for a 7 days
LocalDate old = LocalDate.of(2017, 6, 29);
LocalDate current = LocalDate.of(2017, 7, 1);
System.out.println(old.plusDays(7).isBefore(current));
old = LocalDate.of(2017, 6, 23);
System.out.println(old.plusDays(7).isBefore(current));
The output will be
false
true
You can use ChronoUnit to measure days/months/years/weeks between two dates
LocalDate date1 = LocalDate.of( 2017, 10, 10 );
LocalDate date2 = LocalDate.of( 2017, 11, 10 );
long years = ChronoUnit.YEARS.between( date1, date2 );
long months = ChronoUnit.MONTHS.between( date1, date2 );
long days = ChronoUnit.DAYS.between( date1, date2 );
long weeks = ChronoUnit.WEEKS.between( date1, date2 );

finding the day based on date in java - gives incorrect answer

java.util.Date gives incorrect day as output.
java.util.Date date = new Date(2014,03,01);
System.out.println("day is" +date.getDay());
output : day is 3
actually it should be 7
Update : Thanks a lot I was able to get the output Here is my code
java.util.Calendar c = java.util.Calendar.getInstance();
c.clear();
c.set(year,month,dd);
System.out.println("day of week "+c.get(java.util.Calendar.DAY_OF_WEEK));
I guess you wanted to create the date March 1st 2014. But with your constructor call you create the date April 1st 3914!
The API tells you why:
A year y is represented by the integer y - 1900.
A month is represented by an integer from 0 to 11; 0 is January, 1 is February, and so forth; thus 11 is December.
A date (day of month) is represented by an integer from 1 to 31 in the usual manner.
EDIT: Also this constructor is deprecated. Use Calendar instead.
As per the javadoc of getDay()
Returns the day of the week represented by this date. The returned
value (0 = Sunday, 1 = Monday, 2 = Tuesday, 3 = Wednesday, 4 =
Thursday, 5 = Friday, 6 = Saturday) represents the day of the week
that contains or begins with the instant in time represented by this
Date object, as interpreted in the local time zone.
so its not day of month. Also note that you are using deprecated Date constructor and methods. You can achieve the same using java.util.Calendar
Also month 03 is not March, its April
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, 2014);
c.set(Calendar.MONTH, 3);
c.set(Calendar.DAY_OF_MONTH, 1);
System.out.println(c.get(Calendar.DAY_OF_WEEK));
Here also the output is 3 because, the date represents April 1st 2014, which is Tuesday and as per Calendar.DAY_OF_WEEK doc
Field number for get and set indicating the day of the week. This
field takes values SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
FRIDAY, and SATURDAY.
And Calendar.TUESDAY is 3

Categories