Why are months off by one with Java SimpleDateFormat? - java

I am using SimpleDateFormat to display a Calendar like this :
public String getDate()
{
String DATE_FORMAT = "EEEE, dd/MM/yyyy HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
System.err.println(date.getTime().getMonth());
return sdf.format(date.getTime());
}
The shell returns 6 and the display : mardi, 06/07/2010 12:44:52
It can't be possible ? Why ?
Thanks

From the Java API:
public int getMonth()
Returns a number representing the month that contains or begins with the instant in time represented by this Date object. The value returned is between 0 and 11, with the value 0 representing January.

Unfortunately, months in class Date and class Calendar are zero-based. (In my opinion, this was a huge design mistake in those classes, and it's just one of the many design mistakes in Java's date and time API).
Note that class Calendar has constants to represent the months: Calendar.JANUARY, Calendar.FEBRUARY etc. Use those instead of the raw numbers.
An often mentioned, much better date and time API for Java is Joda Time. Note that there is a proposal to add a new date and time API to the next version of Java that will be based on Joda Time.

the getMonth method in Date is 0 indexed. from the JavaDoc:
Returns a number representing the month that contains or begins with the instant in time represented by this Date object. The value returned is between 0 and 11, with the value 0 representing January.

month index starts from 0 just like array index

that's your locale set to france DD/MM/YY so it is tuesday, July, 2010.
the 6th month is july if it starts at 0.

Related

How to print date 9999-99-99 in xmlgregoriancalendar?

Need to print the date exactly as "9999-99-99" using xmlgregoriancalendar type.
When i pass "9999-99-99" i get wrong output: 10007-07-08. How do i get output exactly as 9999-99-99
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
public class XMLGregorianCalendar {
public static void main(String[] args) {
/* Create Date Object */
//Date date = new Date();
javax.xml.datatype.XMLGregorianCalendar xmlDate = null;
//GregorianCalendar gc = new GregorianCalendar(2001,12,12);
GregorianCalendar gc = new GregorianCalendar(9999,99,99);
// gc.setTime(date);
try{
xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("XMLGregorianCalendar :- " + xmlDate);
}
}
Don’t
The XMLGregorianCalendar class was for dates and/or times for XML documents. Assuming that this was also your purpose, you must not put 9999-99-99 there. It’s not a valid date according to XML rules. Quoting XML Schema Part 2: Datatypes Second Edition, appendix D ISO 8601 Date and Time Formats:
M -- represents a digit used in the time element "month". The two digits in a MM format can have values from 1 to 12.
D -- represents a digit used in the time element "day". The two digits in a DD format can have values from 1 to 28 if the month value
equals 2, 1 to 29 if the month value equals 2 and the year is a leap
year, 1 to 30 if the month value equals 4, 6, 9 or 11, and 1 to 31 if
the month value equals 1, 3, 5, 7, 8, 10 or 12.
I have taken it out of context, but I think that we should understand that dates in XML documents need to be valid dates. 9999-99-99 is not a valid date since there is no month 99 and no month has 99 days in it.
If you wanted 9999-99-99 for something else than an XML document, I don’t think you should be using XMLGregorianCalendar at all. Without context I dare not suggest alternatives.
java.time I said “was … for XML documents”. Dates and times in XML documents are inspired from ISO 8601 formats and close enough that we usually can use the classes from java.time, the modern Java date and time API rather than XMLGregorianCalendar for them and still get the correct syntax from the toString methods of those classes. So also for valid dates consider using the modern LocalDate from java.time rather than the old XMLGregorianCalendar.
You cannot
XMLGregorianCalendar imposes the restriction of a valid date, so cannot print 9999-99-99.
What happened in your code was that GregorianCalendar tacitly and confusingly modified the date into a valid one. Try for example:
GregorianCalendar gc = new GregorianCalendar(9999,99,99);
System.out.println(gc.getTime());
On my computer I got:
Sun Jul 08 00:00:00 CEST 10007
When given invalid month and day of month, GregorianCalendar just keeps counting months and days into the following years. Since 99 months is a little more than 8 years, we end up more than 8 years after January 9999, and a further 3 months because of the 99 days. This was then the date that you passed to your XMLGregorianCalendar, which explains the output you got.
Links
XML Schema Part 2: Datatypes Second Edition, appendix D ISO 8601 Date and Time Formats
Wikipedia article: ISO 8601
Oracle tutorial: Date Time explaining how to use java.time.

Calendar.Month gives wrong output

I have been using java.util for all date and calendar representations. But I am facing a strange problem here. Calendar.MONTH, Calendar.DAY_OF_MONTH, etc all give wrong outputs. But when I use Calendar.getTime(), I get the right output. What might be the problem?
public class TestClass {
public static void main(String[] args) {
Calendar rightNow = Calendar.getInstance();
System.out.println(rightNow.MONTH);
System.out.println(rightNow.DAY_OF_MONTH);
System.out.println(rightNow.YEAR);
System.out.println(rightNow.getTime());
}
}
And the output for the same is:
2
5
1
Tue Jan 22 10:31:44 GMT+05:30 2013
System.out.println(rightNow.MONTH);
System.out.println(rightNow.DAY_OF_MONTH);
System.out.println(rightNow.YEAR);
System.out.println(rightNow.getTime());
You are printing Calendar constant values.
If you want values, you need to do get....
Example:
System.out.println(rightNow.get(Calendar.MONTH));
Read Calendar javadoc for more information.
Calendar.MONTH doesn't return the current month. It is a constant whose value is 2.
From the source:
public final static int MONTH = 2;
It is for use as a parameter in Calendar's get method
public int get(int field) {...}
The design of Calendar is from the early days of Java, when many of today's conventions were different, non-existant, or developing. Oracle (and earlier, Sun), would never let an API like the java.util.Calendar API become part of the standard API today.
And, for completeness, use Joda Time instead of Java's Date and Calendar API's.
java.time
ZonedDateTime rightNow = ZonedDateTime.now(ZoneId.of("Africa/Cairo"));
System.out.println(rightNow.getMonth());
System.out.println(rightNow.getMonthValue());
System.out.println(rightNow.getDayOfMonth());
System.out.println(rightNow.getYear());
System.out.println(rightNow);
Output when running just now was:
FEBRUARY
2
15
2019
2019-02-15T21:15:06.313809+02:00[Africa/Cairo]
Don’t use Calendar
The Calendar class is confusing and suffers from poor design, so no wonder that you’re wondering. Fortunately it was replaced the year after you asked this quesion by ZonedDateTime and other classes in java.time, the modern Java date and time API. So never use Calendar again now.
The Calendar class was trying to be very general, so instead of a getMonth method, etc., it had the notion of fields that could be read and set. Since it was designed long before Java had enums, each field had a number and a named constant for that number. So YEAR (of era) was 1, MONTH was 2, etc. To get the value of the field of a Calendar object you were supposed to call the get method passing the appropriate named constant, for example rightNow.get(Calendar.MONTH). Using just rightNow.MONTH is a regularly repeated mistake. It just gives you the value of the constant, 2.
Link
Oracle tutorial: Date Time explaining how to use java.time.
Calendar now = Calendar.getInstance();
out.println("month now= " + (now.get(Calendar.MONTH)+1));
OR with GregorianCalender:
GregorianCalendar nu = new GregorianCalendar();
int day = nu.get(Calendar.DAY_OF_MONTH);
int month = (nu.get(Calendar.MONTH)+1); //month +1 because january`==0
int year= nu.get(Calendar.YEAR);
int hour= nu.get(Calendar.HOUR_OF_DAY);
int minutes= nu.get(Calendar.MINUTE);
here

Require help for SWT DateTime in Java

I retrieve a Date from the database using the ResultSet rsExpid.
Date joindate = rsExpid.getDate("join_date_ad");
System.out.println(joindate);
int year = joindate.getYear();
System.out.println(year);
int month =joindate.getMonth();
System.out.println(month);
int day = joindate.getDay();
System.out.println(day);
dateTimeJoin4.setDate(year, month, day);
When I print joindate to the console it shows correctly as 2011-08-03, but when I print the year to the console I was amazed to see 111. Similarly printing the month produced 7 and the day resulted in 3.
The variable dateTimeJoin4 is my SWT DateTime. It is not setting any value and it is also not giving any error message. Could please anybody help me on this?
Chances are you haven't read the documentation for Date.getYear and Date.getMonth:
Returns a value that is the result of subtracting 1900 from the year that contains or begins with the instant in time represented by this Date object, as interpreted in the local time zone.
and
Returns a number representing the month that contains or begins with the instant in time represented by this Date object. The value returned is between 0 and 11, with the value 0 representing January.
respectively. Likewise Date.getDay returns the day of the week, not the day of the month - you want Date.getDate() for that (or preferrably a different API entirely, either Calendar or Joda Time).
This has nothing to do with SWT's DateTime type - after all, you only use that in the last line. When something behaves unusually, your first port of call should be the documentation. SWT's DateTime.setDate method is documented to require a year between 1752 and 9999, so 111 will be confusing it. Admittedly it would have been nice if it had thrown an exception, but even so...
The fact that you're calling deprecated methods should have been a hint to you, although Calendar also uses 0-11 for its months.
Personally I would strongly encourage you to use Joda Time for as much of your date and time work as you can. It's a far superior date and time API to the one built into Java. It's not immediately clear whether it's worth you using it here (if this is all you have to do) but if you're doing anything at all significant (including parsing, formatting or any kind of arithmetic) you should be using it.
I tried using this method and it worked correctly so this method can be useful to other.
Calendar startCal = Calendar.getInstance();
startCal.setTime(joindate);
int months= startCal.get(Calendar.MONTH);
int years= startCal.get(Calendar.YEAR);
int days= startCal.get(Calendar.DAY_OF_MONTH);
System.out.println(months+1);
System.out.println(years);
System.out.println(days);
dateTimeJoin4.setDate(years, months+1, days);
getDay() return the position of the day not the date like suppose today is Monday it will return 1, it start from the sunday with 0 value.
as well as the getMonth() return the position as starting value is 0 for january at now you getting the 7 instead of 8.
for getting date you can use the SimpleDateFormat or DateFormat by passing the format string in that you can get it
example links
http://www.roseindia.net/java/javadate/date-format.shtml
http://www.java-examples.com/java-simpledateformat-class-example

Is this a date in February or in March? cal.set(2010, 1, 10)

I have set this calendar in my app:
Calendar cal = Calendar.getInstance();
cal.set(2010, 1, 10);
I'm using this SimpleDateFormat to get the month as a word:
SimpleDateFormat formatMonth = new SimpleDateFormat("MM");
In one class it comes out as February 10th, 2010.
In another it comes out as March 10th, 2010.
Which is correct?
The month argument to Calendar.set() is zero-based, so 1 means February. The first behavior is the correct one.
I suspect something in your other class is mistakenly trying to compensate for zero-based month indexes, and that results in an off-by-one error.
The calendar class has constants for months
Calendar.JANUARY
for example. You should be using those.
Given all the hassles associated with the JDK date handling, you should really be looking to use Joda time instead. The above code would be rewritten as
DateTime dt = new DateTime().withDate(2010,2,10).withTime(12,13,14,0);
and represents 10 February 2010 at 12:13:14.000 in UTC. No ambiguity, thread safe and immutable.
You should note that SimpleDateFormat is not thread safe.

Date formatter is not formatting the date correctly

I wrote this following java code to format the date and time in specific formats. You can see the below code at ideone .
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.text.SimpleDateFormat;
class timeAndDateTransformation{
public static void main(String[] argv){
Calendar newDate = new GregorianCalendar(2009,7,1,15,20,00);
SimpleDateFormat dateFormant = new SimpleDateFormat("yyyy/MM/dd");
SimpleDateFormat timeFormant = new SimpleDateFormat("HH:mm:ss");
System.out.println(dateFormant.format(newDate.getTime()).toString());
System.out.println(timeFormant.format(newDate.getTime()).toString());
}
}
Its giving me following output:
2009/08/01
15:20:00
In this output rest all it perfectly okay, except the month. I passed 7 as a month but in this for-matter output its giving 8 as a output. Please point me where am i doing wrong. I am not very familiar with the date/calendar classes of java, so please bear with me.
Months are 0-based, you passed in 7 so that resolves to August.
From the api docs for java.util.Date:
A month is represented by an integer from 0 to 11; 0 is January, 1 is February, and so forth; thus 11 is December.
It's really counter-intuitive to make the month zero-based. I think we've all gotten burned by that one at some point.
The month field in Java is zero based. GregorianCalendar.JANUARY is 0...etc etc.
Therefore, if you want to pass in a date into the constructor, add one to the month value.
If you look at the [JavaDoc here][1], it explains it for you.
[1]: http://download.oracle.com/javase/1.4.2/docs/api/java/util/Calendar.html#set(int, int, int)
Humans like to see the first month (January) being 1, so that's what SimpleDateFormat does.
However computers like to see things starting from 0, and that's how GregorianCalendar manages the month param. See the constructors for GregorianCalendar and the description of the month parameter.
[Java considers January month 0. ][1] But when you output the month number with SimpleDateFormat it uses the standard January is month 1 system. So month 7 is outputted as 8.
If you are having trouble with the JDK's date and calendar consider using Joda Time, it's much easier
[1]: http://download.oracle.com/javase/1.4.2/docs/api/java/util/GregorianCalendar.html#GregorianCalendar(int, int, int)

Categories