java get week of year for given a date
how can I get a week of the year given a date? I tried the following code:
Calendar sDateCalendar = new GregorianCalendar();
sDateCalendar.set(Integer.parseInt(sDateYearAAAA), Integer.parseInt(sDateMonthMM)-1, Integer.parseInt(sDateDayDD));
System.out.format("sDateCalendar %tc\n", sDateCalendar);
iStartWeek = sDateCalendar.getWeekYear();
System.out.println("iStartWeek "+iStartWeek+ " "+sDateCalendar.WEEK_OF_YEAR);
and i obtain: sDateCalendar lun apr 23 11:58:39 CEST 2012 iStartWeek 2012 3
while the correct week of year is 17. Can someone help me ?
tl;dr
For a year-week defined by the ISO 8601 standard as starting on a Monday and first week contains the first Thursday of the calendar year, use the YearWeek
class from the ThreeTen-Extra library that adds functionality to the java.time classes built into Java.
org.threeten.extra.YearWeek
.from(
LocalDate.of( 2012 , Month.APRIL , 23 )
)
.toString()
2012-W17
Definition of a Week
You need to define week-of-year.
- One common definition is that week # 1 has January 1.
- Some mean week # 1 is the first week of the year holding the first day of the week (such as Sunday in the United States).
- The standard ISO 8601 meaning is that week # 1 holds the first Thursday, and the week always begins with a Monday. A year can have 52 or 53 weeks. The first/last week can be have a week-based year different than the calendar year.
Beware that the old java.util.Calendar class has a definition of week that varies by Locale.
For many reasons, you should avoid the old java.util.Date/.Calendar classes. Instead use the new java.time framework.
java.time
Java 8 and later comes with the java.time framework. Inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project. See Tutorial.
Here is some example code to getting the ISO 8601 standard week.
Getting a date, and therefore a week, depends on the time zone.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );
The IsoFields
class defines a week-based year. We can ask for the:
- Week-of-year number (
WEEK_OF_WEEK_BASED_YEAR
) - Year number of the week-based year (
WEEK_BASED_YEAR
).
First we get the current date-time.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
Interrogate that date-time object, asking about the standard week-based year.
int week = now.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
int weekYear = now.get ( IsoFields.WEEK_BASED_YEAR );
Dump to console.
System.out.println ( "now: " + now + " is week: " + week + " of weekYear: " + weekYear );
now: 2016-01-17T20:55:27.263-05:00[America/Montreal] is week: 2 of weekYear: 2016
For more info, see this similar Question: How to calculate Date from ISO8601 week number in Java
WeekFields
In java.time you can also call upon the WeekFields
class, such as WeekFields.ISO.weekBasedYear()
. Should have the same effect as IsoFields
in later versions of Java 8 or later (some bugs were fixed in earlier versions of Java 8).
YearWeek
For standard ISO 8601 weeks, consider adding the ThreeTen-Extra library to your project to use the YearWeek
class.
YearWeek yw = YearWeek.of( 2012 , 17 ) ;
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
.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
-
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
- Java 9 brought some minor features and fixes.
-
Java SE 6 and Java SE 7
- Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
-
Android
- Later versions of Android (26+) bundle implementations of the java.time classes.
- For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
- If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
elegant way (no need for java.util.Calendar):
new SimpleDateFormat("w").format(new java.util.Date())
You are using sDateCalendar.WEEK_OF_YEAR, which is the static integer WEEK_OF_YEAR, see the source of the java.util.Calendar class:
public final static int WEEK_OF_YEAR = 3;
To get the week number, you should be using:
sDateCalendar.get(Calendar.WEEK_OF_YEAR);
Calendar calendar = Calendar.getInstance(Locale.WHATEVER);
calendar.set(year, month, day);
calendar.get(Calendar.WEEK_OF_YEAR);
Be careful with month in Calendar, as it starts with 0, or better use Calendar.WHATEVER_MONTH