java get week of year for given a date - java

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

Related

Java SWT DateTime: Determine day of Week

I have a DateTime widget with 3/9/2017. Based on the documentation for DateTime, I don't see a way to determine the day of the week. I'll eventually need a string parsed in this format "Wed Feb 22 14:57:34 UTC 2017" from the DateTime widget, but the first step is to get the day of the week. Is there a way to do this outside of making my own function? And if not, what would you recommend as the best approach for the function, since days of the week are not consistent to dates from year to year?
Let me know if you need any addition information.
Thank you!
Use java.util.Calendar:
Calendar c = Calendar.getInstance();
c.setTime(yourDate);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
if you need the output to be Tue rather than 3 (Days of week are indexed starting at 1), instead of going through a calendar, just reformat the string: new SimpleDateFormat("EE").format(date) (EE meaning "day of week, short version")
Documentation
tl;dr
LocalDate.of( 2017 , Month.MARCH , 9 )
.getDayOfWeek()
.getDisplayName( TextStyle.FULL , Locale.ITALY )
Or…
OffsetDateTime.now( ZoneOffset.UTC )
.format( DateTimeFormatter.RFC_1123_DATE_TIME )
java.time
The modern approach uses the java.time classes that supplanted the troublesome old date-time classes.
The DayOfWeek enum defines seven objects, one for each day of the week, Monday-Sunday.
The LocalDate class represents a date-only value without time-of-day and without time zone.
DayOfWeek dow = LocalDate.now().getDayOfWeek() ;
Generate a string of the localized name.
String output = dow.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH ) ; // Or Locale.US etc.
To generate your longer string for a moment, use DateTimeFormatter to specify a custom pattern, use a built-in pattern, or automatically localize.
String output = OffsetDateTime.now( ZoneOffset.UTC ).format( DateTimeFormatter.RFC_1123_DATE_TIME ) ;
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.
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.
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 (<26), 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.

Get last day of specific(SEPTEMBER) month

How to get the fiscal year end date (2017-09-30) dynamically.
Based on the year I need to get the fiscal year end date dynamically.
For example:
If 2017 then output should be 2017-09-30
If 2018 then output should be 2018-09-30 and so on.
Code:
Calendar.getInstance().getActualMaximum(Calendar.SEPTEMBER);
Output I am getting as "4"
Can I know how to get the end date dynamically.
This will help you
private static String getDate(int month, int year) {
Calendar calendar = Calendar.getInstance();
// passing month-1 because 0-->jan, 1-->feb... 11-->dec
calendar.set(year, month - 1, 1);
calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
Date date = calendar.getTime();
DateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy");
return DATE_FORMAT.format(date);
}
Fiscal year?
The term “fiscal year” is not defined here. Usually that is a company-specific definition, and may not be as simple as “end of September”.
Avoid legacy date-time classes
If you are asking for the same month and same day-of-month but adjusted by year, use the java.time classes. The troublesome Calendar class is now legacy, and should be avoided.
LocalDate & MonthDay
The LocalDate class represents a date-only value without time-of-day and without time zone.
The MonthDay class represents a month and day-of-month without any year and without any time zone.
LocalDate ld = LocalDate.of( 2017 , Month.SEPTEMBER , 30 );
MonthDay md = MonthDay.from( ld );
LocalDate ldInAnotherYear = md.atYear( ld.getYear() + 1 );
You could also simply add a year depending on the date in question and what your desired behavior is for handling the last days of a month since months have different lengths, and of course February has the issue of Leap Year.
LocalDate yearLater = LocalDate.of( 2017 , Month.SEPTEMBER , 30 ).plusYears( 1 );
YearMonth
You might find the YearMonth class handy. You can ask it for the last day of the month.
YearMonth ym = YearMonth( 2017 , Month.SEPTEMBER );
LocalDate endOfMonth = ym.atEndOfMonth();
I recommend using objects rather than mere integers. Consider passing around objects such as YearMonth, MonthDay, LocalDate, and Month where appropriate rather than numbers.
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 get year returns wrong result

I want to create a calendar object and set it to a certain year and a week in that year.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.WEEK_OF_YEAR, weekOfYear); // 1
calendar.set(Calendar.YEAR, year); // 2016
setWeekChecked(calendar);
This is the toString of the calendar object as I pass it to the setWeekChecked method:
java.util.GregorianCalendar[time=?,areFieldsSet=false,lenient=true,zone=America/New_York,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=0,WEEK_OF_YEAR=1,WEEK_OF_MONTH=2,DAY_OF_MONTH=7,DAY_OF_YEAR=7,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=5,HOUR_OF_DAY=5,MINUTE=25,SECOND=43,MILLISECOND=219,ZONE_OFFSET=-18000000,DST_OFFSET=0]
In the setWeekChecked method:
public void setWeekChecked(final Calendar cal) {
final int targetWeek = cal.get(Calendar.WEEK_OF_YEAR); // Returns 1
final int targetYear = cal.get(Calendar.YEAR); // Returns 2015??
}
This is the toString of the calendar object now:
java.util.GregorianCalendar[time=1451557543219,areFieldsSet=true,lenient=true,zone=America/New_York,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2015,MONTH=11,WEEK_OF_YEAR=1,WEEK_OF_MONTH=5,DAY_OF_MONTH=31,DAY_OF_YEAR=365,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=5,HOUR_OF_DAY=5,MINUTE=25,SECOND=43,MILLISECOND=219,ZONE_OFFSET=-18000000,DST_OFFSET=0]
What am I doing wrong?
I suspect that the calendar is trying to use the current day-of-week (it's Thursday today) in the first week of 2016.
Now, looking at your calendar settings, you've got firstDayOfWeek=1 (so weeks run Sunday to Saturday) and minimalDaysInFirstWeek=1 (so the first week of the year is the one that includes January 1st).
That means that the first week of 2016 in your calendar ran from Decemember 27th 2015 to January 2nd 2016. Therefore Thursday in the first week was December 31st - which is exactly what the calendar you've shown us says.
Fundamentally, calendar arithmetic with "week of year" is tricky because:
There are lots of different culture-specific ways of looking at them
Typically requirements don't specify which of those you're actually interested in
I'd strongly recommend using Joda Time if at all possible to make your date/time-handling code clearer to start with, but you'll still need to work out exactly what you mean by "set it to a certain year and a week in that year". Note that Joda Time separates the concepts of "week-year" (used with week-of-week-year and day-of-week) from "year" (used with month and day-of-month) which helps greatly. You need to be aware that for a given date, the week-year and year may be different.
tl;dr
LocalDate.of( 2016 , Month.JULY , 1 )
.with( IsoFields.WEEK_OF_WEEK_BASED_YEAR , 1 )
Details
The Answer by Jon Skeet is correct. Update: We have a better way.
The java.time classes built into Java 8 and later supplant the troublesome old legacy date-time classes bundled with the earliest versions of Java. And java.time officially supplants Joda-Time, as that project is now in maintenance mode.
As Skeet points out, there are different ways to define week-of-year.
The java.time classes provide support for the standard ISO 8601 definition of week-of-year. This definition is that week number 1 is the first week with a Thursday, and that week starts on a Monday. So the beginning of the week may include one or more days of the previous year, and the last week may include one or more days from the following year. The year always has either 52 or 53 weeks.
See my Answer to a similar Question for more details.
The LocalDate class represents a date-only value without time-of-day and without time zone.
Get a date near the middle of the desired year. That desired year is a week-based year rather than a calendar year, so must avoid the very beginning or ending of the calendar year. In your case, you wanted week-based year of 2016.
LocalDate ld = LocalDate.of( 2016 , Month.JULY , 1 ) ;
Next we adjust that date into the desired week by using IsoFields.WEEK_OF_WEEK_BASED_YEAR.
LocalDate dayIn2016W01 = ld.with( IsoFields.WEEK_OF_WEEK_BASED_YEAR , 1 ) ;
If you want the first day of that week, use another TemporalAdjuster from the TemporalAdjusters class.
LocalDate firstDayOf2016W01 = dayIn2016W01.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) );
Tip: When Android becomes more capable, use the YearWeek class from the ThreeTen-Extra project.
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….

java.util.Date to java.sql.Date conversion gives wrong month

Consider the following snippet:
Calendar futureDate = Calendar.getInstance();
int year = 2011;
int month = 11;
int day = 14;
futureDate.set(year,month, day);
System.out.println(futureDate.toString());
java.sql.Date sqlDate = new java.sql.Date( futureDate.getTime().getTime());
The printout from futureDate.toString() is:
.....YEAR=2011,MONTH=11,WEEK_OF_YEAR=43,WEEK_OF_MONTH=4,DAY_OF_MONTH=14,DAY_OF_YEAR=289,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=3,AM_PM=0,HOUR=11,HOUR_OF_DAY=11,MINUTE=32,SECOND=51,MILLISECOND=117,ZONE_OFFSET=-18000000,DST_OFFSET=3600000]
which shows that the Calendare object holds the correct date. However, after converting to sql date and storing in the database (MySQL through JDBC), the MySQL table shows '2011-12-14' for this date instead of '2011-11-14'.
I would have suspected locale and time zone, but these would cause discrepancy in the time of day not in the month part of the date.
Any clues to what I did wrong?
Calendar#set(int, int, int) interprets the month argument as zero-based, so futureDate.set(2011, 11, 14) sets the calendar's month to December.
tl;dr
LocalDate.of( 2011 , 11 , 14 ) // November 14th, 2011
Details
The Answer by Matt Ball is correct. But now there is a much improved way.
java.time
The troublesome old date-time classes such as Calendar, java.util.Date, and java.sql.Date are now legacy, supplanted by the java.time classes.
Unlike the legacy classes, the java.time classes have sane numbering, such as months being numbered 1-12 for January to December, and 1-7 for Monday to Sunday.
The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate ld = LocalDate.of( 2011 , 11 , 14 ) ;
Or use the handy Month enum.
LocalDate ld = LocalDate.of( 2011 , Month.NOVEMBER , 14 ) ;
With a JDBC driver supporting JDBC 4.2 and later, you may pass your java.time objects directly to the database.
myPreparedStatement.setObject( … , ld ) ;
When fetching, use getObject.
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
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
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.

What is a good, simple way to compute ISO 8601 week number?

Suppose I have a date, i.e. year, month and day, as integers. What's a good (correct), concise and fairly readable algorithm for computing the ISO 8601 week number of the week the given date falls into? I have come across some truly horrendous code that makes me think surely there must be a better way.
I'm looking to do this in Java but psuedocode for any kind of object-oriented language is fine.
tl;dr
LocalDate.of( 2015 , 12 , 30 )
.get (
IsoFields.WEEK_OF_WEEK_BASED_YEAR
)
53
…or…
org.threeten.extra.YearWeek.from (
LocalDate.of( 2015 , 12 , 30 )
)
2015-W53
java.time
Support for the ISO 8601 week is now built into Java 8 and later, in the java.time framework. Avoid the old and notoriously troublesome java.util.Date/.Calendar classes as they have been supplanted by java.time.
These new java.time classes include LocalDate for date-only value without time-of-day or time zone. Note that you must specify a time zone to determine ‘today’ as the date is not simultaneously the same around the world.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
Or specify the year, month, and day-of-month as suggested in the Question.
LocalDate localDate = LocalDate.of( year , month , dayOfMonth );
The IsoFields class provides info according to the ISO 8601 standard including the week-of-year for a week-based year.
int calendarYear = now.getYear();
int weekNumber = now.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
int weekYear = now.get ( IsoFields.WEEK_BASED_YEAR );
Near the beginning/ending of a year, the week-based-year may be ±1 different than the calendar-year. For example, notice the difference between the Gregorian and ISO 8601 calendars for the end of 2015: Weeks 52 & 1 become 52 & 53.
ThreeTen-Extra — YearWeek
The YearWeek class represents both the ISO 8601 week-based year number and the week number together as a single object. This class is found in the ThreeTen-Extra project. The project adds functionality to the java.time classes built into Java.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
YearWeek yw = YearWeek.now( zoneId ) ;
Generate a YearWeek from a date.
YearWeek yw = YearWeek.from (
LocalDate.of( 2015 , 12 , 30 )
)
This class can generate and parse strings in standard ISO 8601 format.
String output = yw.toString() ;
2015-W53
YearWeek yw = YearWeek.parse( "2015-W53" ) ;
You can extract the week number or the week-based-year number.
int weekNumber = yw.getWeek() ;
int weekBasedYearNumber = yw.getYear() ;
You can generate a particular date (LocalDate) by specifying a desired day-of-week to be found within that week. To specify the day-of-week, use the DayOfWeek enum built into Java 8 and later.
LocalDate ld = yw.atDay( 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.
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.
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 adds 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 bundle implementations of the java.time classes.
For earlier Android (<26), 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.
I believe you can use the Calendar object (just set FirstDayOfWeek to Monday and MinimalDaysInFirstWeek to 4 to get it to comply with ISO 8601) and call get(Calendar.WEEK_OF_YEAR).
/* Build a calendar suitable to extract ISO8601 week numbers
* (see http://en.wikipedia.org/wiki/ISO_8601_week_number) */
Calendar calendar = Calendar.getInstance();
calendar.setMinimalDaysInFirstWeek(4);
calendar.setFirstDayOfWeek(Calendar.MONDAY);
/* Set date */
calendar.setTime(date);
/* Get ISO8601 week number */
calendar.get(Calendar.WEEK_OF_YEAR);
The joda-time library has an ISO8601 calendar, and provides this functionality:
http://joda-time.sourceforge.net/cal_iso.html
yyyy-Www-dTHH:MM:SS.SSS This format of
ISO8601 has the following fields:
* four digit weekyear, see rules below
* two digit week of year, from 01 to 53
* one digit day of week, from 1 to 7 where 1 is Monday and 7 is Sunday
* two digit hour, from 00 to 23
* two digit minute, from 00 to 59
* two digit second, from 00 to 59
* three decimal places for milliseconds if required
Weeks are always complete, and the
first week of a year is the one that
includes the first Thursday of the
year. This definition can mean that
the first week of a year starts in the
previous year, and the last week
finishes in the next year. The
weekyear field is defined to refer to
the year that owns the week, which may
differ from the actual year.
The upshot of all that is, that you create a DateTime object, and call the rather confusingly (but logically) named getWeekOfWeekyear(), where a weekyear is the particular week-based definition of a year used by ISO8601.
In general, joda-time is a fantastically useful API, I've stopped using java.util.Calendar and java.util.Date entirely, except for when I need to interface with an API that uses them.
Just the Java.util.Calendar can do the trick:
You can create a Calendar instance and set the First Day Of the Week
and the Minimal Days In First Week
Calendar calendar = Calendar.getInstance();
calendar.setMinimalDaysInFirstWeek(4);
calendar.setFirstDayOfWeek(Calendar.MONDAY);
calendar.setTime(date);
// Now you are ready to take the week of year.
calendar.get(Calendar.WEEK_OF_YEAR);
This is provided by the javaDoc
The week determination is compatible with the ISO 8601 standard when
getFirstDayOfWeek() is MONDAY and getMinimalDaysInFirstWeek() is 4,
which values are used in locales where the standard is preferred.
These values can explicitly be set by calling setFirstDayOfWeek() and
setMinimalDaysInFirstWeek().
The Calendar class almost works, but the ISO week-based year does not coincide with what an "Olson's Timezone package" compliant system reports. This example from a Linux box shows how a week-based year value (2009) can differ from the actual year (2010):
$ TZ=UTC /usr/bin/date --date="2010-01-01 12:34:56" "+%a %b %d %T %Z %%Y=%Y,%%G=%G %%W=%W,%%V=%V %s"
Fri Jan 01 12:34:56 UTC %Y=2010,%G=2009 %W=00,%V=53 1262349296
But Java's Calendar class still reports 2010, although the week of the year is correct.
The Joda-Time classes mentioned by skaffman do handle this correctly:
import java.util.Calendar;
import java.util.TimeZone;
import org.joda.time.DateTime;
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTimeInMillis(1262349296 * 1000L);
cal.setMinimalDaysInFirstWeek(4);
cal.setFirstDayOfWeek(Calendar.MONDAY);
System.out.println(cal.get(Calendar.WEEK_OF_YEAR)); // %V
System.out.println(cal.get(Calendar.YEAR)); // %G
DateTime dt = new DateTime(1262349296 * 1000L);
System.out.println(dt.getWeekOfWeekyear()); // %V
System.out.println(dt.getWeekyear()); // %G
Running that program shows:
53 2010 53 2009
So the ISO 8601 week number is correct from Calendar, but the week-based year is not.
The man page for strftime(3) reports:
%G The ISO 8601 week-based year (see NOTES) with century as a decimal number. The
4-digit year corresponding to the ISO week number (see %V). This has the same for‐
mat and value as %Y, except that if the ISO week number belongs to the previous or
next year, that year is used instead. (TZ)
If you want to be on the bleeding edge, you can take the latest drop of the JSR-310 codebase (Date Time API) which is led by Stephen Colebourne (of Joda Fame). Its a fluent interface and is effectively a bottom up re-design of Joda.
this is the reverse: gives you the date of the monday of the week (in perl)
use POSIX qw(mktime);
use Time::localtime;
sub monday_of_week {
my $year=shift;
my $week=shift;
my $p_date=shift;
my $seconds_1_jan=mktime(0,0,0,1,0,$year-1900,0,0,0);
my $t1=localtime($seconds_1_jan);
my $seconds_for_week;
if (#$t1[6] < 5) {
#first of january is a thursday (or below)
$seconds_for_week=$seconds_1_jan+3600*24*(7*($week-1)-#$t1[6]+1);
} else {
$seconds_for_week=$seconds_1_jan+3600*24*(7*($week-1)-#$t1[6]+8);
}
my $wt=localtime($seconds_for_week);
$$p_date=sprintf("%02d/%02d/%04d",#$wt[3],#$wt[4]+1,#$wt[5]+1900);
}

Categories