SimpleDateformat and "Day of week in month" (F) - java

I would like to get which day of the week is the current day and looking the SimpleDateFormat class I tought that the "F" is what I need. So I wrote a little test:
System.out.println(new SimpleDateFormat("F").format(new Date()));
Today is wednesday and I expect to get 3 as output. Instead I get 2.
As english isn't my mothertongue, did I missunderstand the meaning of the format?

F - Day of week in month
E - Day name in week
try u - Day number of week (1 = Monday, ..., 7 = Sunday)
Note that 'u' is since Java 7, but if you need just day number of the week then use Calendar
Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.DAY_OF_WEEK));
You can change first day of week by changing Locale or directly as
c.setFirstDayOfWeek(Calendar.SUNDAY);

Today is the second Wednesday in the current month.

The java.util.Calendar/.Date and related classes are a confusing mess as you have learned the hard way. Counting from zero for month numbers and day-of-week numbers is one of many poor design choices made in those old classes.
java.time
Those old classes have been supplanted in Java 8 and later by the java.time framework. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
DayOfWeek
For day of week, use the well-named DayOfWeek enum.
If you want an integer for day-of-week compliant with ISO 8601 where Monday = 1 and Sunday = 7, you can extract that from an instance of DayOfWeek.
Conversion
If starting with a java.util.Calendar object, convert to java.time.
An Instant is a moment on the timeline in UTC.
Instant instant = myJavaUtilCalendarObject.toInstant();
Apply a time zone in order to get a date in order to get a day-of-week.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
DayOfWeek dayOfWeek = zdt.getDayOfWeek();
Note that time zone in crucial in determining a date, and therefore a day-of-week. The date is not the same around the world simultaneously. A new day dawns earlier in Paris than in Montréal, for example.
Number Of Day-Of-Week
Now that we have java.time and this enum built into Java, I suggest you freely pass around those enum instances rather than a magic number.
But if you insist on an integer, ask the DayOfWeek.
int dayOfWeekNumber = dayOfWeek.getValue();
String Of Day-Of-Week
That enum generates a localized String for the name of the day-of-week.
String output = dayOfWeek.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH ); // Or Locale.ENGLISH.

Indexes for the days of week start from 0, not 1.

F -> Day of week in month(1-5)
Today is - 09/01/2013(dd/MM/yyyy) which fall 2nd in week so it has printed 2.
If you try with 16/01/2013 then it would print 3.

F = Day of Week in Month
1day to 7day, it will print 1.
8day to 14day, it will print 2.
15day to 21day, it will print 3.
22day to 28day, it will print 4 and
29day to 31day, it will print 5.

just use this method for this.
public String day(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("EEEEEEEEE", new Locale("tr", "TR"));
return sdf.format(date);
}

Related

Get week span as pair of zero-based day-of-year (0-364 or 0-365) numbers in Java

I need to get week span: start of week (Mo) | end of week (Sun) in days of year.
For example, for 5.9.2019, it should be 241-247 (days starting from 0).
However, my method produces 250 | 249
public static Pair<Integer, Integer> getWeekSpan(Timestamp date) {
Pair<Integer, Integer> result = new Pair<Integer, Integer>();
Calendar cal = timestampToCalendar(date);
// start of week
cal.set(Calendar.DAY_OF_WEEK, cal.getActualMinimum(Calendar.DAY_OF_WEEK));
result.setKey(cal.get(Calendar.DAY_OF_YEAR) - 1);
// end of week
cal.set(Calendar.DAY_OF_WEEK, cal.getActualMaximum(Calendar.DAY_OF_WEEK));
result.setValue(cal.get(Calendar.DAY_OF_YEAR) - 1);
return result;
}
public static Calendar timestampToCalendar(Timestamp timestamp) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timestamp.getTime());
return cal;
}
java.time
public static Pair<Integer, Integer> getWeekSpan(LocalDate date) {
return new Pair<>(getZeroBasedDayOfYear(date.with(DayOfWeek.MONDAY)),
getZeroBasedDayOfYear(date.with(DayOfWeek.SUNDAY)));
}
private static int getZeroBasedDayOfYear(LocalDate date) {
return date.getDayOfYear() - 1;
}
Output:
[244, 250]
It doesn’t agree exactly with what you said you expected, but it does agree with what I get from running the code in your own answer, so I trust that it is correct. The numbers correspond to Monday, September 2 and Sunday, September 8, 2019.
I don’t know whether your Pair class has got a 2-argument constructor. If not, I trust you to fill in the two integers in the same way you did in the question.
Beware that a week may cross New Year. If for instance I specify 2019-12-31, I get:
[363, 4]
4 refers to January 5 of the following year.
My code relies on the fact that you want ISO weeks, where Monday is the first day of the week. If required, we can introduce more flexibility through a WeekFields object:
public static Pair<Integer, Integer> getWeekSpan(LocalDate date) {
WeekFields wf = WeekFields.ISO;
return new Pair<>(getZeroBasedDayOfYear(date.with(wf.dayOfWeek(), 1)),
getZeroBasedDayOfYear(date.with(wf.dayOfWeek(), 7)));
}
As long as I use WeekFields.ISO, the result is still the same, but this is where you might plug in, for example WeekFields.of(Locale.getDefault()) if you wanted to use the week definition of the default locale.
The classes you were using, Timestamp and Calendar, are poorly designed and long outdated. I recommend you don’t use them. Instead I am using LocalDate from java.time, the modern Java date and time API.
If you’ve got a Timestamp object from a legacy API that you cannot change or don’t want to upgrade just now, the way to convert to a LocalDate is:
LocalDate convertedLocalDate = yourTimestamp.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
What went wrong in your code?
This is one of the places where the Calendar class is getting confusing. It numbers the days of the week from 1 for Sunday through 7 for Saturday. So when you ask for the actual minimum and maximum, you get 1 for Sunday and 7 for Saturday even though these are not the first and the last day of the week. So what happened was that you first set the day of week to Sunday, yielding September 8 because your week starts on Monday. BTW, Calendar.getInstance() picks up the week definition from your default locale, which cannot be read from the code and is likely to confuse many too. And even more so if one day your code runs on a JVM with a different default locale and suddenly behaves differently. Next when setting the day of the week to max, 7, you got Saturday, September 7. The dates were translated correctly to 250 and 249.
Link
Oracle tutorial: Date Time explaining how to use java.time.
Converting between legacy and modern date-time classes
If you must start with a java.sql.Timestamp because of interoperating with old code not yet updated to java.time classes, you can convert back and forth.
Instant
You will find new to…/from… conversion methods added to the old classes. The java.sql.Timestamp class offers the toInstant method to render a java.time.Instant object. Both the old and new classes represent a moment in UTC with a resolution of nanoseconds.
Instant instant = myJavaUtilTimestamp.toInstant() ;
The next problem is that we have a moment in UTC, a point on the timeline. But your business problem requires a date on the calendar. The trick is that for any given moment the date varies around the globe by time zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
ZonedDateTime
So you must specify the time zone by which you want determine a date. Apply a ZoneId to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
LocalDate
The zdt represents the very same simultaneous moment as the instant. The difference is that the zdt is viewed through the offset used by the people of that time zone’s region. We can therefore extract the date (year-month-day) from that ZonedDateTime as seen by the people of Québec at that moment, given this example. The date-only value is represented by the LocalDate class, having no time-of-day and no time zone.
LocalDate localDate = zdt.toLocalDate() ;
Now, with this localDate object in hand, you may follow the instructions in this Answer by Ole V.V.
Setting straignt Monday and Sunday solved the problem.
public static Pair<Integer, Integer> getWeekSpan(Timestamp date) {
Pair<Integer, Integer> result = new Pair<Integer, Integer>();
Calendar cal = timestampToCalendar(date);
// start of week
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
result.setKey(cal.get(Calendar.DAY_OF_YEAR) - 1);
// end of week
cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
result.setValue(cal.get(Calendar.DAY_OF_YEAR) - 1);
return result;
}
EDIT: However this piece of code does solve the initial problem, it does not solve time zone problem and uses deprecated classes. See other answers for more detail.

Printing Time and Date in both Universal Time and Standard Time

Writing a Java application that takes user input into a Time and Date class, but I am not sure how to take this user input and convert it into Universal and Standard time... I have spent multiple hours surfing the web and stack overflow and have not been able to find a solution.
I have hours, minutes, seconds, year, month, day all in separate integer variables and need to display them in Universal and Standard time.
Thanks for taking a look...
There are two solutions:
first is place all of input in the string and parse it:
String dateStr = ""
//put your input in this string in some format/ example:
//dateSttr = year + "." + month + "." + day + " " + hour + ":" + minute;
//It is better to use StringBuilder
DateFormat inputFormat = new SimpleDateFormat("yyyy.MM.dd hh:mm");
//note that hh is 12h-format and HH is 24h-format
DateFormat outputFormat1 = new SimpleDateFormat("your_outputFormat");
DateFormat outputFormat2 = new SimpleDateFormat("your_another_outputFormat");
Date date = inputFormat.parse(dateStr);
String o1, o2;
o1 = outputFormat1.format(date);
o2 = outputFormat2.format(date);
//o1 and o2 is your result.
For the rules, how this formats is done, see javadoc
The second solution is to get a new date and set your parameters:
Calendar cln = Calendar.getInstance().clear();
//by default you get a calendar with current system time
//now set the fields. for example, day:
cln.set(Calendar.YEAR, 2015);
cln.set(Calendar.MONTH, Calendar.FEBRUARY);
cln.set(Calendar.DAY_OF_MONTH, 17);
cln.set(Calendar.HOUR_OF_DAY, 18);//Calendar.HOUR for 12h-format
cln.set(Calendar.MINUTE, 27);
See more about setting calendar in javadoc
Note, that in the second variant, you might have some fields undefiend.
If #JonSkeet 's assumption and mine is correct, you're starting with either UTC or your local time. Displaying it is just a matter of formatting your output.
For the other type of time, you add or subtract a number of hours, which you can find on the web. The tricky part is that this may push you into the next calendar day, or pull you back into the previous one. To deal with that, I figure you want to either
implement an adder for year, month, day, hour--or
convert those to decimal somethings (Excel uses days, for instance, where as I write this it's 42328.08813), shift the value by the appropriate number of hours, and convert it back.
java.time
The Answer by TEXHIK is correct, but outdated. Also, as others mentioned, I do not know what you mean by "Universal and Standard time". But I'll try to get you part way there.
As of Java 8, the old java.util.Date/.Calendar classes have been supplanted by the new java.time framework. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
The ZonedDateTime class has a factory method taking numbers for year, month, and so on.
Plus you must specify a time zone. If your numbers represent a date-time in UTC, use the ZoneOffset.UTC constant. For other time zones, specify a ZoneId object by using a proper time zone name; never use the 3-4 letter codes such as EST or IST as their are neither standardized nor unique.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
// ZoneId zoneId = ZoneOffset.UTC; // ZoneOffset is a subclass of ZoneId.
ZonedDateTime zdt = ZonedDateTime.of( 2015 , 1 , 2 , 3 , 4 , 5 , 6 , zoneId );
zdt: 2015-01-02T03:04:05.000000006-05:00[America/Montreal]
You can convert to UTC or another time zone.
ZonedDateTime zdt_Kolkata = zdt.withZoneSameInstant ( ZoneId.of("Asia/Kolkata") );
ZonedDateTime zdt_Utc = zdt.withZoneSameInstant ( ZoneOffset.UTC );
zdt_Kolkata: 2015-01-02T13:34:05.000000006+05:30[Asia/Kolkata]
zdt_Utc: 2015-01-02T08:04:05.000000006Z
If working with classes not yet updated for java.time, convert to a java.util.Date. First extract a Instant object, a moment on the timeline always in UTC.
java.util.Date date = java.util.Date.from ( zdt.toInstant () );

Printing the correct date with Java GregorianCalendar Class

I'm trying to print a few things, such as today's date, the day of the week, the date that it will be 100 days from now, the day of the week one hundred days from now, my birthday and day of the week, and 10,000 days after my birthday and that day of the week. Now, I understand that the GregorianCalendar starts at 0 for January and goes to 11 for December. I get that, so it makes sense that when I attempt to print the date it says today's date is 8/25/12 rather than 9/25/12, but I have no idea how to correct this without setting the date ahead an extra month and then actually putting the month into October rather than September.
Here is what I'm dealing with currently.
GregorianCalendar cal = new GregorianCalendar();
int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
int month = cal.get(Calendar.MONTH);
int year = cal.get(Calendar.YEAR);
int weekday = cal.get(Calendar.DAY_OF_WEEK);
cal.add(Calendar.DAY_OF_MONTH, 100);
int dayOfMonth2 = cal.get(Calendar.DAY_OF_MONTH);
int month2 = cal.get(Calendar.MONTH);
int year2 = cal.get(Calendar.YEAR);
int weekday2 = cal.get(Calendar.DAY_OF_WEEK);
GregorianCalendar birthday = new GregorianCalendar(1994, Calendar.JANUARY, 1);
int dayOfMonth3 = birthday.get(Calendar.DAY_OF_MONTH);
int month3 = birthday.get(Calendar.MONTH);
int year3 = birthday.get(Calendar.YEAR);
int weekday3 = birthday.get(Calendar.DAY_OF_WEEK);
birthday.add(Calendar.DAY_OF_MONTH, 10000);
int weekday4 = birthday.get(Calendar.DAY_OF_WEEK);
int dayOfMonth4 = birthday.get(Calendar.DAY_OF_MONTH);
int month4 = birthday.get(Calendar.MONTH);
int year4 = birthday.get(Calendar.YEAR);
System.out.printf("Todays date is " +month + "/" +dayOfMonth +"/" +year +".");
System.out.printf(" It is day " +weekday +" of the week");
System.out.println("");
System.out.printf("In 100 days it will be " +month2 + "/" +dayOfMonth2 +"/" +year2 +". ");
System.out.printf("Day " +weekday2 +" of the week");
System.out.println("");
System.out.printf("My Birthday is " +month3 + "/" +dayOfMonth3 +"/" +year3 +". "+"Day " +weekday3 +" of the week");
System.out.println("");
System.out.printf("10,000 days after my birthday is " +month4 + "/" +dayOfMonth4 +"/" +year4 +". " +"Day " +weekday4 +" of the week");
So I need help correcting the month for today's date, the date in 100 days, the date of my birthday, and 10,000 days after my birthday. Any help or insight is much appreciated.
I get that, so it makes sense that when I attempt to print the date it says today's date is 8/25/12 rather than 9/25/12, but I have no idea how to correct this without setting the date ahead an extra month
If you are going to print the month by doing
int month = cal.get(Calendar.MONTH);
...
System.out.printf("Todays date is " + month + ...
Then you want to print month + 1, not just month.
Ultimately though you are going to save a lot more time and headache by just using SimpleDateFormat for formatting Dates as Strings.
Yes, you need to know that Calendar.JANUARY equals zero. Months are zero-based for Calendar.
You're working far too hard here. You're dealing too much with primitives.
Here's how to print today's date:
DateFormat formatter = new SimpleDateFormat("yyyy-MMM-dd");
formatter.setLenient(false);
Date today = new Date();
System.out.println(formatter.format(today));
Here's how to get 100 days from now:
Calendar calendar = Calendar.getInstance();
calendar.setTime(today);
calendar.add(Calendar.DAY_OF_YEAR, 100);
Date oneHundredDaysFromToday = calendar.getTime();
System.out.println(formatter.format(oneHundredDaysFromToday));
Stop dealing with all those int values.
tl;dr
LocalDate.now()
.toString() // Expecting January 23, 2018.
2018-01-23
LocalDate.now()
.plusDays( 10 )
.toString() // Expecting February 2, 2018.
2018-02-02
Avoid legacy date-time classes
The Calendar and GregorianCalendar classes are confusing, poorly-designed, and troublesome. Avoid these classes and the related old legacy date-time classes. Now supplanted by the java.time classes.
java.time
today's date,
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Day of week
the day of the week,
The DayOfWeek class represents a day-of-week from Monday to Sunday. Pass these objects around your code rather than a mere integer 1-7.
DayOfWeek dow = ld.getDayOfWeek() ;
If you must have a number, get 1-7 for Monday-Sunday per ISO 8601 standard.
int dowNumber = ld.getDayOfWeek().getValue() ; // Number 1-7 for Monday-Sunday.
Adding days
the date that it will be 100 days from now, the day of the week one hundred days from now, my birthday and day of the week, and 10,000 days after my birthday and that day of the week.
Add and subtracting days is simple, using plus… and minus… methods.
LocalDate later = ld.plusDays( 10 ) ; // Ten days later.
Alternatively, use a Period to represent a number of years-months-days.
Period p = Period.ofDays( 10 ) ;
LocalDate later = ld.plus( p ) ;
One hundred days or 10,000 days would be added the same way.
LocalDate later = ld.plusDays( 10_000 ) ;
Numbering
Now, I understand that the GregorianCalendar starts at 0 for January and goes to 11 for December
The java.time classes use sane numbering, unlike the legacy classes.
The number 2018 is the year 2018. No math with 1900.
Months are numbered 1-12 for January-December.
Days of the week are numbered 1-7 for Monday-Sunday, per the ISO 8601 standard.
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
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, 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.

What is the difference between Calendar.WEEK_OF_MONTH and Calendar.DAY_OF_WEEK_IN_MONTH in Java's Calendar class?

Java's Calendar class provides for two fields: WEEK_OF_MONTH and DAY_OF_WEEK_IN_MONTH. Can someone explain the difference to me? It seems that they both return the same value when tested using the code below:
Calendar date = Calendar.getInstance();
date.set(2011,5,29);
int weekNo1 = date.get(Calendar.WEEK_OF_MONTH);
int weekNo2 = date.get(Calendar.DAY_OF_WEEK_IN_MONTH);
Calendar.WEEK_OF_MONTH simply returns "Current week number in current month"
Calendar.DAY_OF_WEEK simply returns "Current day number in current week starting on last Sunday"
Calendar.DAY_OF_WEEK_IN_MONTH returns "N if current day is Nth day of month" say "3 if today is 3rd Wednesday in month"
So I am writing this on 21st December 2016:
And this is what I am getting:
Calendar today = Calendar.getInstance();
System.out.println(today.get(Calendar.DAY_OF_WEEK)); //outputs 4, as today is 4th day in this week which started on 18
System.out.println(today.get(Calendar.DAY_OF_WEEK_IN_MONTH)); //outputs 3, as today is "3rd Wednesday of this month". Earlier two wednesday were on 7th and 14th
System.out.println(today.get(Calendar.WEEK_OF_MONTH)); //outputs 4, as currently 4th week of a month is running
The difference is that DAY_OF_WEEK_IN_MONTH provides the number of times the weekday has occurred during the month and WEEK_OF_MONTH just returns the week number within the current month. Think of it this way, if the month starts on a Wednesday, the first Monday will occur during the second week of the month. The value for DAY_OF_WEEK_IN_MONTH for that Monday would be 1, but the WEEK_OF_MONTH would be 2.
I found all of the other docs confusing, so for any Microsoft developers like myself this one might be clear for you, as it was for me:
http://msdn.microsoft.com/en-us/library/aa986432(v=vs.80).aspx
A constant representing a value for how many times a given day has
occurred in the month.
You must also take in count that Calendar.getInstance depends on Locale. So, you sometimes could have to specify a concrete Locale instead of the default Locale, for instance: Calendar.getInstance(new Locale("es","PE").
For the example, avobe, Calendar.getInstance(new Locale("es","PE") the calendar will consider first days of the week the Mondays, in other Locales could be other days
tl;dr
Calendar.WEEK_OF_MONTH
Obsolete, never use Calendar.
Means the nth week within a month, with definition varying by Locale and the result of getFirstDayOfWeek().
If you want to define a week as week-of-month # 1 is the week containing day-of-month 1, then use: LocalDate::get( ChronoField.ALIGNED_WEEK_OF_MONTH )
Calendar.DAY_OF_WEEK_IN_MONTH
Obsolete, never use Calendar.
Means the nth day-of-week within that month, such 2nd Tuesday, where weeks are defined as week # 1 containing day 1 of that month.
Replaced by LocalDate::get( ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH )
Avoid Calendar legacy class
Be aware that the Calendar class used in the question is terrible, and was supplanted years ago by the modern java.time classes defined in JSR 310. Do not use Calendar nor GregorianCalendar. They were designed by people who did not understand date-time handling.
java.time
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
LocalDate ld = LocalDate.of( 2020 , Month.JANUARY , 23 ) ; // 2020-01-23.
Convert
If given a Calendar object that is really a GregorianCalendar, you can easily convert to a modern ZonedDateTime object.
GregorianCalendar gc = ( GregorianCalendar ) myCalendar ; // Cast from more general class to the concrete class underlying.
ZonedDateTime zdt = gc.toZonedDateTime() ;
Extract the date-only portion.
LocalDate ld = zdt.toLocalDate() ; // Extract the date, omitting the time-of-day and the context of a time zone.
ChronoField
You can interrogate a LocalDate object via the get method with various ChronoField enum objects.
Calendar.WEEK_OF_MONTH
This asks for the week of the month. But how do you define a week of the month? Unfortunately, the Calendar class’ definition varies by Locale. So your results may vary at runtime.
If your definition is that week # 1 has the first day of the calendar month, you can interrogate a LocalDate using ChronoField.ALIGNED_WEEK_OF_MONTH.
int weekOfMonth = ld.get( ChronoField.ALIGNED_WEEK_OF_MONTH ) ;
Calendar.DAY_OF_WEEK_IN_MONTH
This means the nth day-of-week found in the month, such as 2nd-Tuesday or third-Thursday. Unlike Calendar.WEEK_OF_MONTH, this definition does not vary by Locale. Week # 1 is the week containing day-of-month 1. This legacy Calendar class really is an awful mess, confusing and inconsistent. Good riddance.
Now in java.time, use instead ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH.
DayOfWeek dow = ld.getDayOfMonth() ; // Get enum object representing day of week such as `DayOfWeek.MONDAY`.
int nthDayOfWeekOfMonth = ld.get( ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH ) ;
Week of Month is the week within the current month starting from sundays how many weeks have there been.
Day of week of month is the day 5 would be Thursday, 1 sunday ect.

Why dec 31 2010 returns 1 as week of year?

For instance:
Calendar c = Calendar.getInstance();
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
c.setTime( sdf.parse("31/12/2010"));
out.println( c.get( Calendar.WEEK_OF_YEAR ) );
Prints 1
Same happens with Joda time.
:)
The definition of Week of Year is Locale dependent.
How it is defined in US is discused in the other posts. For example in Germany (DIN 1355-1 / ISO 8601): the first Week* of Year is the first week with 4 or more days in the new year.
*first day of week is Monday and last day of week is Sunday
And Java’s Calendar pays attention to the locale. For example:
public static void main(String[] args) throws ParseException {
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date lastDec2010 = sdf.parse("31/12/2010");
Calendar calUs = Calendar.getInstance(Locale.US);
calUs.setTime(lastDec2010);
Calendar calDe = Calendar.getInstance(Locale.GERMAN);
calDe.setTime(lastDec2010);
System.out.println( "us: " + calUs.get( Calendar.WEEK_OF_YEAR ) );
System.out.println( "de: " + calDe.get( Calendar.WEEK_OF_YEAR ) );
}
prints:
us: 1
de: 52
ADDED
For the US (and I can think of that it is the same for Mexico) the 1. Week of Year is the week where the 1. January belongs to. -- So if 1. Januar is a Saturday, then the Friday before (31. Dec) belongs the same week, and in this case this day belongs to the 1. Week of Year 2011.
Values calculated for the WEEK_OF_YEAR
field range from 1 to 53. Week 1 for a
year is the earliest seven day period
starting on getFirstDayOfWeek() that
contains at least
getMinimalDaysInFirstWeek() days from
that year. It thus depends on the
values of getMinimalDaysInFirstWeek(),
getFirstDayOfWeek(), and the day of
the week of January 1. Weeks between
week 1 of one year and week 1 of the
following year are numbered
sequentially from 2 to 52 or 53 (as
needed).
To determine if that week is the last week of 2010 or the first of 2011 Java uses getMinimalDaysInFirstWeek javadoc. If that method returns 7 then the first week in which all the days in the week are of the same year is week one, if it returns 1 then the first week with any days of the next year is the first week of the next year.
In this case the first of January in 2011 is on a Saturday so it is considered the first week of 2011 as long as you would like a week with one day to be considered already the first week of the next year, if you don't then do:
Calendar c = Calendar.getInstance();
c.setMinimalDaysInFirstWeek(7);//anything more than 1 will work in this year
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
c.setTime( sdf.parse("31/12/2010"));
System.out.println( c.get( Calendar.WEEK_OF_YEAR ) );
returns:
52
tl;dr
java.time.LocalDate.parse(
"31/12/2010" ,
DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.UK )
)
.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR )
52
Or, add a library, and then…
org.threeten.extra.YearWeek.from( // Convert from a `LocalDate` object to a `YearWeek` object representing the entire week of that date’s week-based year.
java.time.LocalDate.parse( "31/12/2010" , DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.UK )
).getWeek() // Extract an integer number of that week of week-based-year, either 1-52 or 1-53 depending on the year.
52
java.time
As others noted, the definition of a week varies by Locale in the old java.util.Calendar class.
That troublesome class, and its partner java.util.Date, have been supplanted by the java.time framework built into Java 8 and later.
The IsoFields class defines a week using the ISO 8601 standard: Week always starts on a Monday, and week # 1 holds the first Thursday of the calendar-year.
Get the current moment.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
Ask about the standard week-based year.
int week = now.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
int weekYear = now.get ( IsoFields.WEEK_BASED_YEAR );
Standard week definition
There are many ways to define “a week” and “first week of the year”.
However, there is one major standard definition: the ISO 8601 standard. That standard defines weeks of the year, including the first week of the year.
the week with the year's first Thursday
A standard weeks begins with Monday and ends with Sunday.
Week # 1 of a week-based year has the first Thursday of the calendar year.
The java.time classes support the ISO 8601 week through the IsoFields class, holding three constants that implement TemporalField:
WEEK_OF_WEEK_BASED_YEAR
WEEK_BASED_YEAR
WEEK_BASED_YEARS
Call LocalDate::get to access the TemporalField.
LocalDate ld = LocalDate.parse( "2010-12-31" ) ;
int weekOfWeekBasedYear = ld.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) ;
int yearOfWeekBasedYear = ld.get( IsoFields.WEEK_BASED_YEAR ) ;
ld.toString(): 2010-12-31
weekOfWeekBasedYear: 52
yearOfWeekBasedYear: 2010
ISO 8601 string format
The ISO 8601 standard defines a textual format as well as a meaning for week-based-year values: yyyy-Www. For a specific date, add day-of-week numbered 1-7 for Monday-Sunday: yyyy-Www-d.
Construct such a string.
String outputWeek = String.format( "%04d" , yearOfWeekBasedYear ) + "-W" + String.format( "%02d" , weekOfWeekBasedYear ) ;
String outputDate = outputWeek + "-" + ld.getDayOfWeek().getValue() ;
2010-W52-5
YearWeek
This work is much easier if you add the ThreeTen-Extra library to your project. Then use the YearWeek class.
YearWeek yw = YearWeek.from( ld ) ; // Determine ISO 8601 week of a `LocalDate`.
Generate the standard string.
String output = yw.toString() ;
2010-W52
And parse.
YearWeek yearWeek = YearWeek.parse( "2010-W52" ) ;
yearWeek.toString(): 2010-W52
Determine a date. Pass a java.time.DayOfWeek enum object for day-of-week Monday-Sunday.
LocalDate localDate = yw.atDay( DayOfWeek.MONDAY ) ;
localDate.toString(): 2010-12-27
I strongly recommending adding this library to your project. Then you can pass around smart objects rather than dumb ints. Doing so makes your code more self-documenting, provides type-safety, and ensures valid values.
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.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor 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, 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.
For much more detail, see my Answer on the similar Question:
java get week of year for given a date
…and see my Answer on the similar Question:
How to calculate Date from ISO8601 week number in Java
IIRC, The first week with a date of Jan 1 is week 1.
That's why week 1 is returned for 12/31/2010.
Try it for 12/31/2011 and you'll get 52.
Edit: Week is locale specific, sometimes defined as Sunday - Saturday, sometimes defined as Monday - Sunday
This is because the start of the week is local dependent.
In the US the Week 1 starts on the Sunday before Jan 1. In 2010 this is Dec 26. That's why Dec 31 is still week 1.
In Europe the week 1 starts on the Monday before Jan 1. In 2010 this is Dec 27. That's why also in Europe Dec 31 is still week 1.
java.time
As also specified in the accepted answer, the Week-of-Year is Locale dependent.
Demo:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.WeekFields;
import java.util.Locale;
class Main {
public static void main(String[] args) {
DateTimeFormatter parser = DateTimeFormatter.ofPattern("dd/MM/uuuu", Locale.ROOT);
LocalDate date = LocalDate.parse("31/12/2010", parser);
System.out.println(date.get(WeekFields.of(Locale.US).weekOfWeekBasedYear()));
System.out.println(date.get(WeekFields.of(Locale.GERMANY).weekOfWeekBasedYear()));
}
}
Output:
1
52
Learn more about the modern Date-Time API from Trail: Date Time.

Categories