Java Calendar returns wrong month
When you use DAY_OF_YEAR
you set the number day of the current year.
- https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#DAY_OF_YEAR
DAY_OF_YEAR Field number for get and set indicating the day number
within the current year.
This overrides all sensible configuration like month or year (to current year and month of the number day).
So instead of use DAY_OF_YEAR
you may use DAY_OF_MONTH
which seems is what you are looking for, this sets the day of the month you set before.
- https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#DAY_OF_MONTH
DAY_OF_MONTH Field number for get and set indicating the day of the month. This is a synonym for DATE. The first day of the month has value 1.
So the configuration you are looking for definetively seems it would be like next:
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.set(Calendar.YEAR, 2017);
cal.set(Calendar.MONTH, Calendar.JUNE);
cal.set(Calendar.DAY_OF_MONTH , 26);
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Then when you call getTime you will get:
Mon Jun 26 11:00:00 CEST 2017
Calendar.MONTH gives wrong value
Keep in mind that months values start from 0
, so October
is actually month number 9
.
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Calendar.html#MONTH
Java Calendar returns wrong date
Your problem isn't the Date
class, but passing the wrong parameter.
Change:
cstart.get(Calendar.DATE)
to
cstart.get(Calendar.DAY_OF_MONTH)
EDIT: This does not solve the issue.
There does seem to be some problem, but since the OP is using in-house developed Date/.. classes, I 'm not going to pursue this further.
For those who want more information about that, check the comments.
Java Gregorian Calendar Returns Wrong Month
tl;dr
To get a number 1-12 for current month:
LocalDate.now()
.getMonthValue()
Better to specify your desired/expected time zone.
LocalDate.now(
ZoneId.of( "America/Montreal" )
).getMonthValue()
Similarly call .getYear()
and .getDayOfMonth()
.
Details
it returns the wrong month
As others said, in Calendar
the months January-December are crazily numbered 0-11 rather than 1-12. One of many poor design decisions in the old date-time classes. Those classes are now legacy, supplanted by the java.time classes.
So is there a work around this?
Yes, there is a workaround. Use a good date-time library rather than the mess that is java.util.Date/Calendar. The modern way is with the java.time classes.
Current moment
Time zone is crucial in getting the current date and time. For any given moment the date and wall-clock time vary by zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( z );
You can interrogate for the various components such as year, month number, localized name of month via Month
enum, and day-of-month.
System.out.println ( "Current: " + zdt );
System.out.println( "Year is " + zdt.getYear() );
System.out.println( "Month is " + zdt.getMonthValue() );
System.out.println( "Month name is " + zdt.getMonth().getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH ) ); // Or Locale.US, Locale.ITALY, etc.
System.out.println( "Day is " + zdt.getDayOfMonth() );
Current: 2016-12-14T04:54:44.802-05:00[America/Montreal]
Year is 2016
Month is 12
Month name is décembre
Day is 14
See live code in IdeOne.com.
If you only care about the date and not the time-of-day, use the LocalDate
class.
LocalDate.now( z );
Specific moment
You can specify a moment as a count of milliseconds since the epoch of first moment of 1970 in UTC.
long input = 1_234_567_898_765L ;
Instant instant = Instant.ofEpochMilli( input );
instant.toString(): 2009-02-13T23:31:38.765Z
The Z
in that output is short for Zulu
and means UTC.
You can assign a time zone to adjust into a particular wall-clock time.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
zdt.toString(): 2009-02-13T18:31:38.765-05:00[America/Montreal]
See live code in IdeOne.com.
I do not recommend exchanging date-time data this way. Better to serialize to text in ISO 8601 formats. For example: 2009-02-13T23:31:38.765Z
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….
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.
Old Answer - Joda-Time
Update: The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
- Use Joda-Time 2.3 now.
- In the future, with Java 8, consider moving to JSR 310: Date and Time API which supplants the Date/Calendar classes and is inspired by Joda-Time.
Example Code
Today
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// Generally best to be explicit about time zone rather than depend on default.
DateTimeZone denverTimeZone = DateTimeZone.forID( "America/Denver" );
java.util.Locale locale = Locale.FRANCE;
DateTime now = new DateTime( denverTimeZone );
System.out.println( "Current Year, Month & Day for: " + now );
System.out.println( "Year is " + now.year().getAsText( locale ) );
System.out.println( "Month is " + now.monthOfYear().getAsText( locale ) );
System.out.println( "Day is " + now.dayOfMonth().getAsText( locale ) );
System.out.println(); // blank line.
When run…
Current Year, Month & Day for: 2013-12-04T01:58:24.322-07:00
Year is 2013
Month is décembre
Day is 4
Some Day
// Not generally a good idea to focus on integers for working with date-time, but you asked for it.
DateTime someDateTime = new DateTime( 1234567898765L, DateTimeZone.UTC );
System.out.println( "Set Value of 1234567898765L is: " + someDateTime );
System.out.println( "Year is " + someDateTime.year().getAsText( locale ) );
System.out.println( "Month is " + someDateTime.monthOfYear().getAsText( locale ) );
System.out.println( "Day of month is " + someDateTime.dayOfMonth().getAsText( locale ) );
System.out.println( "Day of week is " + someDateTime.dayOfWeek().getAsText( locale ) );
System.out.println( "Day of year is " + someDateTime.dayOfYear().getAsText( locale ) );
When run…
Set Value of 1234567898765L is: 2009-02-13T23:31:38.765Z
Year is 2009
Month is février
Day of month is 13
Day of week is vendredi
Day of year is 44
P.S. I just got the chills down my back when I noticed your arbitrarily chosen Long resulted in Friday The Thirteenth!
Calendar returns wrong month and year Java
Those are all static
fields from the Calendar
class. Java allows static
fields (and methods) to be accessed on expressions that resolve to an instance's reference value the same way it does on type names
now.ERA
// is equivalent to
Calendar.ERA
The Calendar
class provides a get(int)
method for getting the value of a date field.
now.get(Calendar.MONTH);
Android - GregorianCalendar displays wrong month
GregorianCalendar
represents months with numbers in the range from 0
to 11
. This means that the number 0
is represented as January and 11
is represented as of December.
Therefore you need to subtract 1
if your API is not using the same logic as the Java implementation.
Updated:GregorianCalendar(2016, 1, 30)
is understood as 30th of February. This is internally converted to 1st of March, therefore when you subtract one month from the date, you get 1st of February. You need to create an instance of GregorianCalendar
class already with the subtracted month number, ie. January as 0, February as 1 and so on.
Calendar.get(Calendar.DAY_OF_MONTH) returning wrong day
Glad that the answer by Robby Cornelissen solved your problem. I should like to explain what happened and why that answer helped.
When you are using the three-arg GregorianCalendar
constructor, it “Constructs a GregorianCalendar
with the given date set in the default time zone with the default locale.” Quoting the docs; italics are mine. In your case this is GMT+3 (now; the important thing is that in August it will still be GMT plus something).
What the docs are not so clear about is that hour of day is set to 0, so you’ve really got a point in time of 10 August 2017 0:00 at zone offset +3:00. You would really have wanted the GregorianCalendar
not to worry about time of day, but there’s no such thing. This is one of the reasons why I recommend LocalDate
instead as I mentioned in a comment.
When you change the time zone, the point in time stays the same, but since you were ahead of GMT in your own time zone, you now have 9 August 2017 21:00 UTC. So 9 is the correct day-of-month value now.
I think the greatest surprise is that the toString
method still produces DAY_OF_MONTH=10
. When GregorianCalendar
computes which fields is obscure to me, but obviously is still remembers the old value at this point.
For formatting you use new SimpleDateFormat("dd")
. This formatter uses your default time zone of GMT+3, and the point in time from the calendar object, correctly producing 10. If you had wanted it to produce the day-of-month from the calendar, you might have set its time zone to UTC too.
dateOfBirth.get(Calendar.DAY_OF_MONTH)
produces the correct value of 9.
The funny thing is that if after this call I repeat your line:
System.out.println("Calendar substring:\t\t"
+ dateOfBirth.toString().substring(dateOfBirth.toString().indexOf("DAY_OF_MONTH"),
dateOfBirth.toString().indexOf("DAY_OF_MONTH") + 15));
This time it produces:
Calendar substring: DAY_OF_MONTH=9,
So that field has now been computed.
In Robby Cornelissen’s code the calendar object is born with UTC time zone, so when you set the date, it is really set to — well, 10 July 2017 this time, but 0:00 UTC. This corresponds to 3:00 in your time zone, but the date is also 10 July there, so the rest of your code will produce the 10 you expected. However, users in time zones west of Greenwich will have problems now because their SimpleDateFormat
will use their time zone, which is behind GMT, so they will see a formatted date of 09
.
For the sake of completeness here’s the ThreeTen (Backport) version:
LocalDate date = LocalDate.of(2017, Month.AUGUST, 10);
System.out.println("Day of month:\t" + date.getDayOfMonth());
This prints
Day of month: 10
A LocalDate
has got neither any time of day nor any time zone, leaving a lot less room for confusion. Contrary to Calendar
it also numbers the months the way humans do, so 7 is July and 8 is August.
Related Topics
How to Create Executable Java Program
Why Isn't There a Java.Lang.Array Class? If a Java Array Is an Object, Shouldn't It Extend Object
Reversing a Linked List in Java, Recursively
Where Do I Find a Standard Trie Based Map Implementation in Java
Make Jackson Interpret Single JSON Object as Array with One Element
Comparing Two Java.Util.Dates to See If They Are in the Same Day
Noclassdeffounderror on Maven Dependency
Java Leaking This in Constructor
Simple Way to Find If Two Different Lists Contain Exactly the Same Elements
Open Resource with Relative Path in Java
Draw a Circle with a Radius and Points Around the Edge
Import Pem into Java Key Store
Java Date Parsing with Microsecond or Nanosecond Accuracy
How to View the SQL Queries Issued by JPA