what does object Calendar do? - java

I had a test for object Calendar:
for (int i = 0; i < 11; i++)
System.out.println(calendar.get(i));
output:
1
2011
6
28
2
6
187
4
1
1
10
My question is how can that happen? There are also the same tricky problems for api calendar.get()

In Calendar.get(i) i represents a field such as ERA, YEAR, MONTH, etc..
For example, calendar.get(1) is the same as calendar.get(Calendar.YEAR) and so on.

I don't see what the problem is. The documentation states that you get the specific values for whatever field ID you provide.
You would normally use the field constants to get specific values (like DAY_OF_MONTH or MONTH but any integer will do provided it's within the range 0..FIELD_COUNT.
The field IDs are documented here (though this may change in future) so your specific values are:
ID Value Description
-- ----- -----------
0 1 Era (BC/AD for Gregorian).
1 2011 Year.
2 6 Month (zero-based).
3 28 Week-of-year.
4 2 Week-of-month.
5 6 Date/day-of-month.
6 187 Day-of-year.
7 4 Day-of-week.
8 1 Day-of-week-in-month.
9 1 AM/PM selector.
10 10 Hour.
That's July 6, 2011 AD, somewhere between 10:00:00 PM and 10:59:59 PM inclusive. The minutes and seconds values are field IDs 12 and 13 and your code doesn't print them out, hence the uncertainty on the time.

The API provided by java.util.Calendar is not very well designed as your confusion illustrates. However take a look at the JavaDoc for get(). The int value is meant to represent the field you want to get the value of. See all of the members listed at that JavaDoc described as "Field number ..." such as YEAR. So calendar.get(Calendar.YEAR) would equal 2011.

The Calendar class is an overkill for many common Date related scenarios. The history is somewhat as follows : The Date class was found to have many deficiencies w.r.t manipulating date objects. Hence the Calendar class was introduced. However, the Calendar class has proved to be an over-engineered solution to many of the common date related scenarios.
Read the Javadoc for better understanding of the Calendar class.

Related

In java.time, why does WeekFields.SUNDAY_START produce a week number of 1 for 2020-12-29 instead of 53?

I'm sure I'm just missing something here, but it continues to elude me.
Why does SUNDAY_START produce a week number of 1 for 2020-12-29 instead of 53?
Is it because I'm misinterpreting what the Oracle docs say? Or am I missing something further?
Details
Going to https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/temporal/WeekFields.html#SUNDAY_START shows that SUNDAY_START appears to follow the same rules as above. If I use the following code...
ZonedDateTime zdt = ZonedDateTime.ofInstant(/* representation of Dec. 29, 2020 */, ZoneId.of("UTC"));
TemporalField wn = WeekFields.SUNDAY_START.weekOfWeekBasedYear();
int weekNumber = zdt.get(wn);
Then "weekNumber" is 1, when I would expect it to be 53.
If I use WeekFields.ISO instead, I get 53; however, the definition of ISO is that it uses Monday as the start of the week, which isn't true in the case I'm dealing with and I'm unsure of future ramifications of just using ISO instead of SUNDAY_START.
What am I missing?
The Answer
Based on the comments below (thank you to Basil and Andreas), I was indeed misreading the Oracle documentation, which states:
Defined as starting on Sunday and with a minimum of 1 day in the month.
The "minimum of 1 day in the month" was the part that threw me for a loop within the context of a new year.
With the clarifications below, it's clear that since Jan. 1, 2021 occurs on a Friday, and the SUNDAY_START week starts on a Sunday, that this week would, in fact, be week number 1 in this case.
Motivation
I had originally asked this question as part of an attempt to better understand SUNDAY_START. The motivation for this was to find a way to recreate MySQL's WEEK() "mode 6" (that is, a Sunday start to the week with week 1 being the first week with 4 or more days this year).
I had forgotten about the ability to create custom week fields with a specified start day and the minimum number of days in the month for it to contain.
Still, I am grateful to have cleared up my misunderstanding of the Javadocs for SUNDAY_START, and I hope this post might be useful to someone in the future.
Thank you for everyone's comments and answers and I apologize for any initial confusion.
https://savvytime.com/week-number is wrong.
When you show Country: United States, Year: 2020, it shows:
Week 53 December 27, 2020 January 2, 2021 Current Week
When you show Country: United States, Year: 2021, it shows:
Week 1 December 27, 2020 January 2, 2021 Current Week
How can the same date range be both week 53 and week 1? It can't. The site is broken.
UPDATE: From comment:
needing a Java datetime "equivalent" of MySQL's WEEK() function using mode 6
That's easy enough. Mode 6 is defined as:
First day of week: Sunday
Week 1 is the first week... with 4 or more days this year
So you get a WeekFields for that:
WeekFields weekMode6 = WeekFields.of(/*firstDayOfWeek=*/DayOfWeek.SUNDAY,
/*minimalDaysInFirstWeek=*/4);
For reference, the two predefined WeekFields instances are defined as:
ISO = new WeekFields(DayOfWeek.MONDAY, 4);
SUNDAY_START = WeekFields.of(DayOfWeek.SUNDAY, 1);
Not so savvy SavvyTime.com
Your linked web site uses undisclosed rules for defining a week:
Weeks are according United States calendar rules, Sunday first day and weeks are Sunday to Saturday
The phrase “United States calendar rules” has no meaning. There are many sets of calendar rules in the US: Various accounting organizations make rules, IRS has rules, industries have their own rules such as a two-season year in some retail, and private companies define their own rules, sometimes quite innovative.
And the rest of that definition is unclear.
Furthermore, that site seems to be inexplicably self-contradictory, as seen in the Answer by Andreas.
I would not consider that web site to be authoritative.
ISO 8601
In contrast, the ISO 8601 calendar is very clearly defined, including the definition of a week and week-based-year:
Weeks start on a Monday, end on Sunday.
Week-based years have either 52 or 53 whole weeks.
Week number 1 contains the first Thursday in the calendar year.
This definition means that a week-based year may contain a few days from the previous calendar year in week # 1, and may contain a few days from the following calendar-year in the last week of the week-based year.
Am not sure exactly what your goal is, as your Question is unclear. But if the ISO 8601 rules match those of your business, then use the implementation in java.time.
ThreeTen-Extra and YearWeek
Even better, add the ThreeTen-Extra library to your project. This library is led by the same man who led the java.time JSR 310 project, Stephen Colebourne. This library brings additional functionality to java.time. In particular, see the YearWeek class for ISO 8601 weeks.

Difference in Months between two LocalDate

I know there's a lot of questions about this but I couldn't find one that match with my case.
I have to know if a date is exactly x months after another.
With ChonoUnit it's just not possible because 2020/05/25 and 2020/07/27or 2020/07/25 will return the same number of month and I can't handle the difference with the days. I have the same type of response with JodaTime
I tried with Perdiod and it's not relevant either.
LocalDate localDate = LocalDate.of(2020,1,30);
LocalDate toTest = localDate.plusMonths(1L); // returns 2020/02/29
Period.between(localDate, toTest);
returns months 0, days 30
I read that the endDate is exclusive, so I tried adding a day
LocalDate localDate = LocalDate.of(2020,1,30);
LocalDate toTest = localDate.plusMonths(1L); // returns 2020/02/29
Period.between(localDate, toTest.plusDays(1L));
returns months 1, days 1
So my question is : Is there a method to get this information that is compatible with the way LocalDate handles the months ?
Edit
Ok, I was not precise enough in my request. I know a month is not an absolute value, and my conception of a month doesn't matter.
In my case I have a LocalDate input that I can't contraint. I have to generate outputs every X months minus Y number of days.
Knowing that I test in a schedule if today is exactly X months after my input minus Y days (to be precise, I test if the number of month between the two dates modulo X equals 0). But if my input is the 31st of the month, Period will never return me 1 months, 0 days. If it's the 30st and my output should trigger in february it will never be neither.
Given that if on the short months the output occurs one day before the inexistant logic date it's not a problem.
The exemple I gave with LocalDate is just extracted from my tests but it's the way I thank I could do the thing, thus without doing myself a complicated algorithm with many conditions.
I think you in your description you tried with January and February. That might be causing problem. So you have to manually handle this case. Otherwise your code is working.
A month is not exact time unit. Think about it: we can tell exactly how many seconds are in 1 minute, in 1 hour, 1 day and 1 week. But the number of seconds for different months would be different. So you need to define the logic what do you see as two dates that differ exactly one month? Once you define all the expected behaviors (including such cases as what is exactly one month from January 30th? Feb 28/29? or march 1st?) then you can see if there is anything out of the box that works for you or you need to implement your own logic
I have to know if a date is exactly x months after another.
That is an unclear request. One obvious interpretation would appear to be:
int monthA = a.getYear() * 12 + a.getMonthValue();
int monthB = b.getYear() * 12 + b.getMonthValue();
// Months.between can probably also be used instead of this math.
return a.getDayOfMonth() == b.getDayOfMonth() && (monthA - monthB) == x;
But that does mean it is -impossible- for a date to exist that is 'exactly 1 month after' March 30th: There is no feb 30th and there never will be.
Is that what you really wanted? Given that the length of a month depends on which month you ask, 'exactly 1 month later' is not a sensible question to ask. Hence: What do you actually mean?
Same day-of-month, X months later? (And realizing that there are many dates for which there cannot be such a date).
X days afterwards, where X is some formulaic approach based on which month we are in.
I probably still haven’t got it. Allow me a shot in spite, elaborating on my idea from the comment: If you like the way LocalDate.plusMonths() does, then use that method.
int monthsBetween = 3; // X
int daysBefore = 11; // Y
LocalDate originalDate = LocalDate.of(2020, Month.JANUARY, 30);
int nextTimeCount = 1; // next time to generate output will be the 1st time
LocalDate nextDate = originalDate.plusMonths(nextTimeCount * monthsBetween).minusDays(daysBefore);
LocalDate today = LocalDate.now(ZoneId.systemDefault());
while (! nextDate.isAfter(today)) {
System.out.format("Generating output no. %d for %s%n", nextTimeCount, nextDate);
nextTimeCount++;
nextDate = originalDate.plusMonths(nextTimeCount * monthsBetween).minusDays(daysBefore);
}
Output when I ran just now (December 30):
Generating output no. 1 for 2020-04-19
Generating output no. 2 for 2020-07-19
Generating output no. 3 for 2020-10-19
Assuming that your program will not be running uninterrupted for months you will need some way to persist the data, of course. So my code will not work as it stands, but if the behaviour is otherwise as expected, you can probably use the same mthod calls that I am using.

GegorianCalendar is giving me 2018 for int month = calendar.get(Calendar.FEBUARY)

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.

SimpleDateFormat error while parsing a date yyyyMMdd format java [duplicate]

In java.util.Calendar, January is defined as month 0, not month 1. Is there any specific reason to that ?
I have seen many people getting confused about that...
It's just part of the horrendous mess which is the Java date/time API. Listing what's wrong with it would take a very long time (and I'm sure I don't know half of the problems). Admittedly working with dates and times is tricky, but aaargh anyway.
Do yourself a favour and use Joda Time instead, or possibly JSR-310.
EDIT: As for the reasons why - as noted in other answers, it could well be due to old C APIs, or just a general feeling of starting everything from 0... except that days start with 1, of course. I doubt whether anyone outside the original implementation team could really state reasons - but again, I'd urge readers not to worry so much about why bad decisions were taken, as to look at the whole gamut of nastiness in java.util.Calendar and find something better.
One point which is in favour of using 0-based indexes is that it makes things like "arrays of names" easier:
// I "know" there are 12 months
String[] monthNames = new String[12]; // and populate...
String name = monthNames[calendar.get(Calendar.MONTH)];
Of course, this fails as soon as you get a calendar with 13 months... but at least the size specified is the number of months you expect.
This isn't a good reason, but it's a reason...
EDIT: As a comment sort of requests some ideas about what I think is wrong with Date/Calendar:
Surprising bases (1900 as the year base in Date, admittedly for deprecated constructors; 0 as the month base in both)
Mutability - using immutable types makes it much simpler to work with what are really effectively values
An insufficient set of types: it's nice to have Date and Calendar as different things,
but the separation of "local" vs "zoned" values is missing, as is date/time vs date vs time
An API which leads to ugly code with magic constants, instead of clearly named methods
An API which is very hard to reason about - all the business about when things are recomputed etc
The use of parameterless constructors to default to "now", which leads to hard-to-test code
The Date.toString() implementation which always uses the system local time zone (that's confused many Stack Overflow users before now)
Because doing math with months is much easier.
1 month after December is January, but to figure this out normally you would have to take the month number and do math
12 + 1 = 13 // What month is 13?
I know! I can fix this quickly by using a modulus of 12.
(12 + 1) % 12 = 1
This works just fine for 11 months until November...
(11 + 1) % 12 = 0 // What month is 0?
You can make all of this work again by subtracting 1 before you add the month, then do your modulus and finally add 1 back again... aka work around an underlying problem.
((11 - 1 + 1) % 12) + 1 = 12 // Lots of magical numbers!
Now let's think about the problem with months 0 - 11.
(0 + 1) % 12 = 1 // February
(1 + 1) % 12 = 2 // March
(2 + 1) % 12 = 3 // April
(3 + 1) % 12 = 4 // May
(4 + 1) % 12 = 5 // June
(5 + 1) % 12 = 6 // July
(6 + 1) % 12 = 7 // August
(7 + 1) % 12 = 8 // September
(8 + 1) % 12 = 9 // October
(9 + 1) % 12 = 10 // November
(10 + 1) % 12 = 11 // December
(11 + 1) % 12 = 0 // January
All of the months work the same and a work around isn't necessary.
C based languages copy C to some degree. The tm structure (defined in time.h) has an integer field tm_mon with the (commented) range of 0-11.
C based languages start arrays at index 0. So this was convenient for outputting a string in an array of month names, with tm_mon as the index.
There has been a lot of answers to this, but I will give my view on the subject anyway.
The reason behind this odd behavior, as stated previously, comes from the POSIX C time.h where the months were stored in an int with the range 0-11.
To explain why, look at it like this; years and days are considered numbers in spoken language, but months have their own names. So because January is the first month it will be stored as offset 0, the first array element. monthname[JANUARY] would be "January". The first month in the year is the first month array element.
The day numbers on the other hand, since they do not have names, storing them in an int as 0-30 would be confusing, add a lot of day+1 instructions for outputting and, of course, be prone to alot of bugs.
That being said, the inconsistency is confusing, especially in javascript (which also has inherited this "feature"), a scripting language where this should be abstracted far away from the langague.
TL;DR: Because months have names and days of the month do not.
In Java 8, there is a new Date/Time API JSR 310 that is more sane. The spec lead is the same as the primary author of JodaTime and they share many similar concepts and patterns.
I'd say laziness. Arrays start at 0 (everyone knows that); the months of the year are an array, which leads me to believe that some engineer at Sun just didn't bother to put this one little nicety into the Java code.
Probably because C's "struct tm" does the same.
Because programmers are obsessed with 0-based indexes. OK, it's a bit more complicated than that: it makes more sense when you're working with lower-level logic to use 0-based indexing. But by and large, I'll still stick with my first sentence.
java.time.Month
Java provides you another way to use 1 based indexes for months. Use the java.time.Month enum. One object is predefined for each of the twelve months. They have numbers assigned to each 1-12 for January-December; call getValue for the number.
Make use of Month.JULY (Gives you 7)
instead of Calendar.JULY (Gives you 6).
(import java.time.*;)
Personally, I took the strangeness of the Java calendar API as an indication that I needed to divorce myself from the Gregorian-centric mindset and try to program more agnostically in that respect. Specifically, I learned once again to avoid hardcoded constants for things like months.
Which of the following is more likely to be correct?
if (date.getMonth() == 3) out.print("March");
if (date.getMonth() == Calendar.MARCH) out.print("March");
This illustrates one thing that irks me a little about Joda Time - it may encourage programmers to think in terms of hardcoded constants. (Only a little, though. It's not as if Joda is forcing programmers to program badly.)
For me, nobody explains it better than mindpro.com:
Gotchas
java.util.GregorianCalendar has far fewer bugs and gotchas than the
old java.util.Date class but it is still no picnic.
Had there been programmers when Daylight Saving Time was first
proposed, they would have vetoed it as insane and intractable. With
daylight saving, there is a fundamental ambiguity. In the fall when
you set your clocks back one hour at 2 AM there are two different
instants in time both called 1:30 AM local time. You can tell them
apart only if you record whether you intended daylight saving or
standard time with the reading.
Unfortunately, there is no way to tell GregorianCalendar which you
intended. You must resort to telling it the local time with the dummy
UTC TimeZone to avoid the ambiguity. Programmers usually close their
eyes to this problem and just hope nobody does anything during this
hour.
Millennium bug. The bugs are still not out of the Calendar classes.
Even in JDK (Java Development Kit) 1.3 there is a 2001 bug. Consider
the following code:
GregorianCalendar gc = new GregorianCalendar();
gc.setLenient( false );
/* Bug only manifests if lenient set false */
gc.set( 2001, 1, 1, 1, 0, 0 );
int year = gc.get ( Calendar.YEAR );
/* throws exception */
The bug disappears at 7AM on 2001/01/01 for MST.
GregorianCalendar is controlled by a giant of pile of untyped int
magic constants. This technique totally destroys any hope of
compile-time error checking. For example to get the month you use
GregorianCalendar. get(Calendar.MONTH));
GregorianCalendar has the raw
GregorianCalendar.get(Calendar.ZONE_OFFSET) and the daylight savings
GregorianCalendar. get( Calendar. DST_OFFSET), but no way to get the
actual time zone offset being used. You must get these two separately
and add them together.
GregorianCalendar.set( year, month, day, hour, minute) does not set
the seconds to 0.
DateFormat and GregorianCalendar do not mesh properly. You must
specify the Calendar twice, once indirectly as a Date.
If the user has not configured his time zone correctly it will default
quietly to either PST or GMT.
In GregorianCalendar, Months are numbered starting at January=0,
rather than 1 as everyone else on the planet does. Yet days start at 1
as do days of the week with Sunday=1, Monday=2,… Saturday=7. Yet
DateFormat. parse behaves in the traditional way with January=1.
The true reason why
You would think that when we deprecated most of Date and added the new
Calendar class, we would have fixed Date's biggest annoyance: the fact
that January is month 0. We certainly should have, but unfortunately
we didn't. We were afraid that programmers would be confused if Date
used zero-based months and Calendar used one-based months. And a few
programmers probably would have been. But in hindsight, the fact that
Calendar is still zero-based has caused an enormous amount of
confusion, and it was probably the biggest single mistake in the Java
international API's.
Quoted from International Calendars in Java by Laura Werner, link at the bottom.
The better alternative: java.time
This may just be repeating what others have said, throw the old and poorly designed Calendar class overboard and use java.time, the modern Java date and time API. There months are consistently sanely numbered from 1 for January through 12 for December.
If you are getting a Calendar from a legacy API not yet upgraded to java.time, the first thing to do is to convert to a modern ZonedDateTime. Depending on your needs you may do further conversions from there. In most of the world the Calendar object you get will virtually always be an instance of the GregorianCalendar subclass (since the Calendar class itself is abstract). To demonstreate:
Calendar oldfashionedCalendarObject = Calendar.getInstance();
ZonedDateTime zdt
= ((GregorianCalendar) oldfashionedCalendarObject).toZonedDateTime();
System.out.println(zdt);
System.out.format("Month is %d or %s%n", zdt.getMonthValue(), zdt.getMonth());
Output when I ran just now in my time zone:
2021-03-17T23:18:47.761+01:00[Europe/Copenhagen]
Month is 3 or MARCH
Links
International Calendars in Java by Laura Werner
Oracle tutorial: Date Time explaining how to use java.time.
tl;dr
Month.FEBRUARY.getValue() // February → 2.
2
Details
The Answer by Jon Skeet is correct.
Now we have a modern replacement for those troublesome old legacy date-time classes: the java.time classes.
java.time.Month
Among those classes is the Month enum. An enum carries one or more predefined objects, objects that are automatically instantiated when the class loads. On Month we have a dozen such objects, each given a name: JANUARY, FEBRUARY, MARCH, and so on. Each of those is a static final public class constant. You can use and pass these objects anywhere in your code. Example: someMethod( Month.AUGUST )
Fortunately, they have sane numbering, 1-12 where 1 is January and 12 is December.
Get a Month object for a particular month number (1-12).
Month month = Month.of( 2 ); // 2 → February.
Going the other direction, ask a Month object for its month number.
int monthNumber = Month.FEBRUARY.getValue(); // February → 2.
Many other handy methods on this class, such as knowing the number of days in each month. The class can even generate a localized name of the month.
You can get the localized name of the month, in various lengths or abbreviations.
String output =
Month.FEBRUARY.getDisplayName(
TextStyle.FULL ,
Locale.CANADA_FRENCH
);
février
Also, you should pass objects of this enum around your code base rather than mere integer numbers. Doing so provides type-safety, ensures a valid range of values, and makes your code more self-documenting. See Oracle Tutorial if unfamiliar with the surprisingly powerful enum facility in Java.
You also may find useful the Year and YearMonth classes.
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, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
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.
Set the month to Calendar.MARCH, or compare to see if it == Calendar.JUNE, for example.
The Date and Calendar classes date back to the very early days of Java, when folks were still figuring things out, and they are widely regarded as not very well designed.
If Calendar were created today with the same design, rather than ints for Calendar.JUNE, etc., they'd use enums.
It isn't exactly defined as zero per se, it's defined as Calendar.January. It is the problem of using ints as constants instead of enums. Calendar.January == 0.
Because language writing is harder than it looks, and handling time in particular is a lot harder than most people think. For a small part of the problem (in reality, not Java), see the YouTube video "The Problem with Time & Timezones - Computerphile" at https://www.youtube.com/watch?v=-5wpm-gesOY. Don't be surprised if your head falls off from laughing in confusion.
In addition to DannySmurf's answer of laziness, I'll add that it's to encourage you to use the constants, such as Calendar.JANUARY.
Because everything starts with 0. This is a basic fact of programming in Java. If one thing were to deviate from that, then that would lead to a whole slue of confusion. Let's not argue the formation of them and code with them.

Parsing String to Dates - Java

This is the problem:
I have some .csv files with travels info, and the dates appear like strings (each line for one travel):
"All Mondays from January-May and October-December. All days from June To September"
"All Fridays from February to June"
"Monday, Friday and Saturday and Sunday from 10 January to 30 April"
"from 01 of November to 30 April. All days except fridays from 2 to 24 of november and sunday from 2 to 30 of december"
"All sundays from 02 december to 28 april"
"5, 12, 20 of march, 11, 18 of april, 2, 16, 30 of may, 6, 13, 27 june"
"All saturdays from February to June, and from September to December"
"1 to 17 of december, 1 to 31 of january"
"All mondays from February to november"
I must parse the strings to Dates, and keep them into an array for each travel.
The problem is that I don't know how to do it. Even my univesrity teachers told me that they don't know how to do so :S. I can't find/create a pattern using http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html
After parsing them i have to search all travels between two dates.
But how? How to parse them? it's possible?
This requires Natural Language Processing (NLP) , see Wikipedia for an account:
http://en.wikipedia.org/wiki/Natural_language_processing.
Your problem as stated is very hard. There are many ways of representing a single date, and your examples include ranges of dates and formulae for generating dates. It sounds as if you have a limited subset of language - frequent use of "all", "from", etc.
If you are in control of the language (i.e. these are being generated by humans who comply with your documentation) then you have a chance of formalising it (although it will take a lot of work - months). If you are not in charge of it, then every time a new phrase appears you will have to add it to the specs.
I suggest you got through the file and look for stock phrases "All [weekdayname]s [from | between | until | before]". Or "in [January | February ...]". Then substitute these in in phrases. If you find this covers all the cases you may be able to extract particular phrases". But if you have anaphora like "next Tuesday" it will be much harder.
You're in the domain of NLP (Natural Language Processing), what is possible or impossible is fuzzy in this domain. From a fast Google search, I've found that the Natty Date Parser might be useful for you.
For more theory background on NLP, you might be interested in Natural Language Processing course of Stanford University on Coursera (at the moment the course is not open for enrolment, but lectures are available for free.
You can also use a set of strict regular expressions that would match only one of your possible cases and apply them from the most restrictive to the most relaxed.
The first thing I would define to attack your problem is what you expect as an output of your method, since in some cases it's a single date, in some cases an interval, in some others multiple intervals.

Categories