I'm newish to Java and am trying to do somethings with dates. First I started using the Date class, which I found out was mostly deprecated so I switched over to Calendar.
Now I am getting weird values. for example the Month value for December is 0, not 12. And on those Calendars where it is giving me 0 for December it is also moving the year ahead one year.
It's weird!
What am I missing?
Thanks for your help.
-GG
EDIT FOR AN EXAMPLE:
So I am reading some line sin from a file such as this:
Johnny Graham H F 12-2-1973 Black
I parse it, and then for the Calendar I set:
int year = Integer.parseInt(stringVersionOfYear); // this value is 1973
Then later when I go to get the year back with a line like this:
calendar.get(Calendar.YEAR)
the value is 1974... And the month is 0 for
cal.get(Calendar.MONTH)
EDIT 2:
I am creating the Calendar like this:
Calendar outputCalendar = Calendar.getInstance();
outputCalendar.set(year, month, day);
The java.util.Date and Calendar classes are poorly designed (eg, the first day in a month is day 1 but the first month in a year is month 0). Many projects use the Joda Time package instead.
Months values are 0 thru 11; set a month to 12 and the date gets "normalized", incrementing the year by one and setting the month to 0. This makes it easy to "add a month" without having to worry about handling the overflow at year end.
EDIT: January=0, February=1,... December=11. When you set the month value to 12 you were asking for the 13th month, which got normalized to the first month of the following year.
Note that this normalization process happens in general -- Try to set the date to December 32nd and you'll get back January 1 of the following year. This means it's important to be careful when modifying individual fields of a Calendar object. If you create a default Calendar on, say, January 31st and then want to modify it to contain, say February 5th, the order in which you set the fields is important. If you change the month first you'll be creating February 31st, which will get normalized to March 2nd or 3rd (depending on the leap year) and then when you set the day to 5 the result is March 5th, not February 5th. You have the opposite problem in other cases, such as starting from any date in February and modifying to the 30th or 31st of any other month. In that case doing the month first results in the same type of problem.
The only safe way to modify a date is to use a method that sets all three values simultaneously, such as the set(int,int,int) method.
See this line?
outputCalendar.set(year, month, day);
Just change it like this:
outputCalendar.set(year, month - 1, day);
and then when you want to get the month, don't use this:
cal.get(Calendar.MONTH)
instead, use this:
(1+(cal.get(Calendar.MONTH)))
It's a pain, but it will fix the problem (I think).
The main piece of advice I have for you is: read the API! Calendar is indeed not the pinnacle of intuitive API design, but it is definitely usable if you take the time to read the javadoc. Learn the difference between .add and .roll. Check out what happens when you set a year (1973) into a Calendar initialized with the current date (default Calendar.getInstance).
Whining about API is all fine (we all do it), but in the end to find solutions start off by reading what the authors provided to you before asking relatively obtuse questions on the Internet.
Related
So Im working on an Calendar programm and to change the Months im asking for the int of the month.
If I type calendar.get(Calendar.JANUARY) i get 1 as return, which is correct because first month. But if I type calendar.get(Calendar.FEBUARY) i get 2018 in respond which of course is wrong. Does anyone know what the problem could be?
Calendar cal1 = new GregorianCalendar();
int month = cal1.get(Calendar.JANUARY);
int month2 = cal1.get(Calendar.FEBRUARY);
int year = cal1.get(Calendar.YEAR);
java.time
T.J. Crowder’s answer is correct. Allow me to supply the real, good and modern solution to your problem.
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Atlantic/Stanley"));
// 2018-05-21T05:02:23.942763-03:00[Atlantic/Stanley]
Month monthEnum = zdt.getMonth(); // MAY
int monthNumber = zdt.getMonthValue(); // 5
int year = zdt.getYear(); // 2018
I ran the code just now and have given results in comments after each code line. Please put your desired time zone where I have put Atlantic/Stanley since the month does not change at the same point in time in different time zones. Do you agree with me that this code is clearer and more natural and leaves less room for confusion? BTW, if you’re only interested in the date, not the time of day, use LocalDate instead of ZonedDateTime, the rest of the code will be the same.
To get the numbers of specific months:
int januaryNumber = Month.JANUARY.getValue(); // 1
int februaryNumber = Month.FEBRUARY.getValue(); // 2
What happened in your code?
As T.J. Crowder has already said, Calendar.get expects a field number, for example Calendar.MONTH or Calendar.YEAR. Calendar.JANUARY is 0. Zero?! It’s another confusing thing about Calendar, month numbers are 0-based, that is, they go from 0 for January through 11 for December. Anyway, 0 is also the field number of Calendar.ERA. GregorianCalendar uses 0 for BC (or more religion neutral: BCE for before common era) and 1 for AD (CE, common era). Since your date is in the common era, you get 1. Which, by the way, would have been incorrect for month of January since months are 0-based.
Similarly, Calendar.FEBRUARY equals 1 and coincides with field number Calendar.YEAR, which I why you got the year.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Question: Why is January month 0 in Java Calendar?
Calendar#get gets a field value. Calendar.JANUARY is not a field number, it's a potential field value. The only static fields in Calendar that you use with get (and set) are the ones whose descriptions start with "Field number for get and set...".
To get the month, use cal1.get(Calendar.MONTH).
The Calendar API is...unfortunate, not least because it predates enums and so int was used for get/set's field identifier parameter where an enum was really needed. While get takes an int, and Calendar.JANUARY is an int, they're ints in different domains. See Ole V.V.'s answer for the modern, dramatically-improved alternative: java.time.
I am a 3 month old java student. For one of my module I tried to make first day of week as tuesday(so that a real friday should now be at index 3) but it didn't show expected result.
I am inputting day through scanner.
Below is the concerned piece of code and output:
Calendar c= Calendar.getInstance();
c.setFirstDayOfWeek(Calendar.TUESDAY);
c.setTime(date);
int dayOfWeek=c.get(Calendar.DAY_OF_WEEK);
System.out.println(dayOfWeek);
Output:
Enter the date(dd/mm/yyyy):
03/07/2014
6
Don't know where I am wrong. Tried a lot googling around and even set minimalDAysOfFirstWeek but nothing working out. What i want is 03/07/2014 to be shown as index 3. How to achieve so?
I think you've misunderstood the purpose of setFirstDayOfWeek.
That doesn't change c.get(Calendar.DAY_OF_WEEK) works at all - it changes the result of calling c.get(Calendar.WEEK_OF_MONTH) and c.get(Calendar.WEEK_OF_YEAR), as per the documentation:
When setting or getting the WEEK_OF_MONTH or WEEK_OF_YEAR fields, Calendar must determine the first week of the month or year as a reference point. The first week of a month or year is defined as the earliest seven day period beginning on getFirstDayOfWeek() and containing at least getMinimalDaysInFirstWeek() days of that month or year.
In other words, Sunday is always Sunday... but whether Sunday June 10th is in the same week as Monday June 11th or not depends on what is considered to be the first day of the week.
switch (c.get(Calendar.DAY_OF_WEEK)) {
case Calendar.TUESDAY:
return 0;
case Calendar.WEDNESDAY:
return 1;
// And so on...
default:
break;
}
I have a little question about internal java working and Calendar, i dont understand why when i use for example:
Calendar c = Calendar.getInstance();
mesInt = c.get(Calendar.MONTH);
System.out.println(mesInt);
If then i print mesInt, if the actually month is february i obtain mesInt = 1;
is there any special reason for that? I would like to know because i had problems before with my database, and i would like if it is possible to know the solution of start by 0 the month.
Thanks for all, and sorry if the questions is duplicated i haven not found it.
PD: i know that is zero-based, but i would like to know the real reason for that.
PD2: sry for my bad english. I know the solution i would like to know the reason of that.
The documentation states the first month is 0.
i would like to know the real reason for that.
I suspect starting at 0 is easier to calculate. I am not sure any one person will admit to designing Calendar. Perhaps it made sense at the time as many of the numberings for years, AM/PM etc start at 0. BTW days of the week start at 1.
know i would like if it is possible to know the solution.
Use
int mesInt = c.get(Calendar.MONTH) + 1;
BTW For me the strange one is UNIDECIMBER when uni-deci mean 11 not 13.
Months are 0 based. I'm not sure of the reason why...
So when using either get or set with month you need to remember to either +1 or -1 as required.
Calendar c = Calendar.getInstance();
int mesInt = c.get(Calendar.MONTH) + 1;
c.set(Calendar.MONTH, mesInt - 1);
Months in Calendar starts from zero it means that January -> 0 February -> 1 etc.
The Specification of Calendar.MONTH is as follows:
Field number for get and set indicating the month. This is a calendar-specific value. The first month of the year in the Gregorian and Julian calendars is JANUARY which is 0; the last depends on the number of months in a year.
Essentially for all practical purposes : January is 0 and December is 11.
I bet it's for the same reason array indices start from 0. It's just how it is. February is often displayed as "2", but displaying or printing values is different from using them in code.
I'd like to have a function which returns the next week and year given a week and year. It looks something like:
public static int[] getNextWeek(int year, int week) {
Calendar c = Calendar.getInstance(); // I'm Locale.US and TimeZone "America/New_York"
c.clear();
c.set(Calendar.YEAR, year);
c.set(Calendar.WEEK_OF_YEAR, week);
c.add(Calendar.WEEK_OF_YEAR, 1);
return new int[] {c.get(Calendar.YEAR), c.get(Calendar.WEEK_OF_YEAR)}
}
This sometimes does not work around year boundaries. It seems to depend on what day you invoke it and for what parameters you use! For example, if I invoke it with year 2012 and week 52 then I expect the result to be year 2013 and week 1. If you invoke it today (Tuesday July 17 2012) it works. If you set the day of week to yesterday it does not; and oddly results in year 2012 week 1. Weird. What is going on? It appears to relate to the day of the week because it doesn't work if invoked with SUNDAY or MONDAY, which are the last two days of 2012! If I set the day of the week to the last day of the week the function seems to work; before calling Calendar.add() I do:
// Must set to last day of week; initially set to first day due to API
c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek()); // SUNDAY
c.add(Calendar.DAY_OF_WEEK, 6); // Must roll forward not backwards
There doesn't seem to be any weirdness like this if I create a getPreviousWeek method. Is this a java.util.Calendar bug? Next time I guess I'll use Joda time!
Have you considered the fact that ISO8601 week algorithm considers the first week of the year to be the one that has at least 4 days fall within that year?
So if the Jan 1 is on thurdsay, that week is actually considered week 52 of the previous year, not week one of the current year.
You might want to at least consider joda-time for this kind of calculation, as it has proper handling of the ISO standard.
LocalDate ld = new LocalDate();
ld = ld.withWeekOfWeekyear(29);
ld = ld.withWeekyear(2012);
System.out.println(ld.getWeekOfWeekyear());
System.out.println(ld.getWeekyear());
// 29
// 2012
System.out.println(ld.plusWeeks(1).getWeekOfWeekyear());
System.out.println(ld.plusWeeks(1).getWeekyear());
// 30
// 2012
And this will work across year boundaries.
Just do an explicit check to see if there's a rollover.
return new int[] {c.get(Calendar.WEEK_OF_YEAR) == 1 ? c.get(Calendar.YEAR) + 1 :
c.get(Calendar.YEAR), c.get(Calendar.WEEK_OF_YEAR)};
As far as I can tell, the reason why WEEK_OF_YEAR doesn't add correctly is because it's not an actual property of Calendar like SECOND, MINUTE, MONTH, DAY, or YEAR. It's a derived property like WEEK_OF_MONTH. One way to get around this is to use c.add(Calendar.DAY, 7) to add exactly 7 days instead of incrementing WEEK_OF_YEAR.
At this point I'm going to assume this really is a bug. I've filled a bug report with Oracle here:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7197761
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