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