I was going through the Calendar class source code in the Java API, and noticed that a lot of variables, e.g. DAY_OF_MONTH, YEAR, etc are declared as static final. This struck me as odd because I thought the date of a Calendar instance should be (1) specific to that instance, i.e. non-static and (2) changeable (so it can be set). Can anyone clarify? Thanks!
It's a manifest constant. It doesn't refer to any particular day of the month, but to the concept DAY_OF_MONTH.
You use it to specify which element of a date you want to get (or set).
E.g., I want to add (increase the Calendar's date by) one month:
c.add ( Calendar.MONTH, 1 )
I want to add one day:
c.add ( Calendar.DAY_OF_YEAR, 1 ) ;
I'm calling the same function, with the first parameter the manifest constant of the Calendar field I want to increment/decrement by. (Of course, incrementing/decrementing by any particular field may change other fields: If I add one day to December 31 2099, The DAY_OF_MONTH, MONTH and YEAR fields will all be changed.)
The alternative would be to have different setters for each field, e.g,
addMonth( int n ) ;
addDayOfYear( int n);
That would make coding some use cases more tedious however.
The OP asks:
Can anyone walk me through what happens, say, when you invoke cal.set(2010, 8, 2) where cal is a Calendar? What I'd like to know is how the compiler connects 2 to DATE_OF_MONTH, or where that 2 ends up in the heap, or what the qualified variable name is under which that 2 is stored. Thanks all who answered!
The "strict" Object Oriented answers is, "as a client programmer using Calendars rather than implementing them, you shouldn't need to know about the Calendar's internal layout or algorithms".
The real answer is that Calendar is an interface, so any particular implementing class could do these things any number of ways, so long as the implementation adheres to the public interface and the semantics of the Calendar interface.
The actual implementation of, say, GregorianCalendar is probably that internally it holds the date as some number of seconds since some special date, e.g, the linux "era" (1 January 1970) or the first institution of the Gregorian Calendar (15 October 15 1582).
So cal.set(2010, 8, 2) probably multiples the year by 365 * 24 * 60 * 60, plus any leap years, the 8 is used to find the number of seconds to the end of the seventh month (again, accounting for a leap day, if any), the 2 adds the number of seconds in two days, etc.
These are keys to the calendar values. The values are obtained by calling calendar.get(key). For example:
int dayOfMonth = concreteCalendar.get(Calendar.DAY_OF_MONTH);
... and if you call myCalendarObject.get(Calendar.DAY_OF_MONTH), then you will get the day of the month corresponding to the date in myCalendarObject, like if it's August 2, you'll get "2".
It might have been more intuitive if they had created functions called "getDayOfMonth", "getMonth", "getYear", and so forth. Maybe this was somehow more efficient to implement, or maybe they were thinking that as the Calendar class is supposed to be extensible to any calendar, so if you wanted to create, say, "MayanCalendar extends Calendar", that you could then define new constants for KATUN and BAKTUN and so forth and it would work with the existing set and get functions.
DAY_OF_MONTH is just an index that identifies which field of the Calendar record represents, well, the day of the month. That's a constant, and that's why it's a constant.
Related
I've scenario where custom financial calendar is defined. Sometimes the month can be of 28 days or sometimes it can be of 35 days as well.
The start of every month varies. (It can start from 10/15/20th)
For referring which calendar date refers to which financial date, I've defined a table which has following column structure:
In above table you can see that fiscalmonth P1 refers to the date 20190125. (It can be the case that fiscalmonth-P1 is starting from 20190115 to 20190215
This table is in database. I'm working on java part to create functionality which will return Periodbetween object based on two fiscal dates provided(which will refer to yyyymmdd column of above table) to function.
public class PeriodBetween {
private int days;
private int weeks;
private int months;
private int quarters;
private int years;
//getters & setters
}
This periodBetween object gives more information about number of days/weeks/months/quarters in between this two dates.
public PeriodBetween between(int startDate, int endDate)
I was looking into something to build like what's there in Java's java.time.Period.between function. But not able to get what best approach I can use by referring to table that is defined above.
Let me know if something like this already exist or there can be other way apart from using Financial Calendar table.
Updates:
The scenario of sometimes the calendar cab be of 28 days or 35 days is based on which calendar is followed by customer. So depending on client the Financial Calendar Table will be populated.
Fiscal Calendar is not predictable. It will be pre populated in table based on requirement.
Yes the Fiscal Calendar Table follow 52 as well as 52 week support. So to give you higher level of idea the table will be populated based on what type of custom calendar is used by customer.
How I am defining my calendar right now ?
Getting the requirement from customer on how they want the calendar to be defined. Using that I'm populating the table mentioned above & using that table everywhere.
So let's say on Financial Calendar I want to find out what is 3rd day of P3 month on Financial year 2018.
Then my query to this table will be to extract more information on this day will be: select * from financial_calendar where fiscaldayofmonth=3 and fiscalmonth=P3 and fiscalyear=Financial Year 2018
My thoughts of calculating number of months between two dates is to extract information from table using between clause of two dates & divide the data size by 30. Which is incorrect.
AccountingChronology
The java.time framework in Java 8 and later defaults to using a chronology based on ISO 8601. However, that chronology is pluggable.
Four other chronology implementations are bundled: Hijrah, Japanese, Minguo, & ThaiBuddhist. Underlying these are the java.time.chrono.Chronology interface, and the java.time.chrono.AbstractChronology class.
The ThreeTen-Extra library adds more functionality to java.time. This includes providing several more Chronology implementations.
One of those is AccountingCalendar. This implementation may suit your needs depending on how you define your fiscal calendar (which you neglected to document in your Question). This chronology is designed to follow the 52/53 week fiscal calendar rules as laid down in IRS Publication 538 and the International Financial Reporting Standards.
Since such a chronology can be defined by each company using the calendar, we need the AccountingChronologyBuilder to define our own company’s definition. Using the builder, we specify:
ending day-of-week - The day-of-week on which a given accounting year ends.
last-in-month vs. nearest-end-of-month - Whether the ending day-of-week is the last in the month, or the nearest to the end of the month (will sometimes be in the next month.
month end - Which Gregorian/ISO end-of-month the year ends in/is nearest to.
year division - How many 'months' (periods) to divide the accounting year into, and how many weeks are in each.
leap-week month - Which month will have the leap 'week' added to it. In practice this is probably the last one, but this does not seem to be required.
The builder object then produces a AccountingChronology for us to use in our app.
From there we can produce AccountingDate objects. This class seems to have much functionality. Notice on this class the method until. To the starting date you provide an ending date, and you get back a java.time.chrono.ChronoPeriod object. From that you might be able to get your count of fiscal months or fiscal weeks. I am not sure, as I have never done any work using this accounting chronology.
FYI, there seems to be a couple other classes involved in this accounting chronology implementation: AccountingEra & AccountingYearDivision.
I'm working on some legacy code where java.util.Calendar is used for date related calculations (basically adding months). Now I want to replace java.util.Calendar by java.time.LocalDate in the code but I don't want to change the behavior. So, I've been looking for a source which clarifies that they yield same result for the same calculation for any case but I can't find any.
Especially I want to know if is there a date that makes them yield a different result between:
Calendar#add(Calendar.MONTH, months)
and
LocalDate#plusMonth(months)
I've tested some corner cases (e.g. a leap year related dates) and they seem to yield the same result but I can't be 100% sure with that. Isn't there any official information about that or some known difference between them?
TL;DR
If:
You are sure that your Calendar is really a GregorianCalendar (by far the most commonly used subclass), and…
Your dates don’t go more than 100 years back, then…
…you can safely use LocalDate#plusMonth(months) instead of Calendar#add(Calendar.MONTH, months).
Details
Congratulations on the decision to migrate from the old and poorly designed Calendar class to LocalDate from java.time, the modern Java date and time API. This will be an improvement to your code base.
You are correct, the methods you mention are used for the same purpose and generally work the same. So when you migrate from Calendar to java.time, if you find that LocalDate is the right new class to use, then you will use LocalDate#plusMonth(months) where you used Calendar#add(Calendar.MONTH, months) before.
Differences include:
The Calendar class is an abstract superclass for classes representing dates (and times) in many different calendar systems (Gregorian, Buddhist and more), a LocalDate is always in the proleptic Gregorian calendar. Since each calendar system has its own definition of what a month is, adding a number of months in a calendar other than the Gregorian calendar can give quite different results from what LocalDate.plusMonths gives you.
If your dates go back in history it will also make a minor difference that LocalDate uses the proleptic Gregorian calendar. This means that it doesn’t use the Julian calendar for dates where it was in use centuries ago.
While Calendar.add modifies the Calendar object that you call it on, LocalDate.plusMonths returns a new LocalDate object with the new date.
While for going backward in the calendar you need to pass a negative number of months to Calendar::add, LocalDate has a convenient minusMonths method that you will typically want to use instead of plusMonths (both work, though).
The range of dates that each class can represent is different. I don’t readily remember the minimum and maximum date for each. On Calendar/GregorianCalendar, see their various methods such as getGreatestMinimum & getLeastMaximum. For LocalDate, see the constants: MAX & MIN.
I am trying to determine the sequential ordinal number of a weekday in a month in Java. i.e. if a Friday is the first or 3rd friday of a month.
I can not find a simple way after reading all the things I can find on Java Calendar and posts here. One way I can think of is to determine how many days the first week of this month have in this month and then adjust week_of_month based on what day the day in question is. However, it requires a little complicated calculation. Anyone knows a simple solution?
Just take the day of month, subtract 1, divide by 7, then add 1. The first seven days of the month are always the first (Tuesday, Wednesday, ...) whatever day of the week the actual 1st of the month is.
Personally I'd use Joda Time:
public int getWeekOfWeekDay(LocalDate date) {
return ((date.getDayOfMonth() - 1) / 7) + 1;
}
... but you could do the same using Calendar and fetching the value of the Calendar.DAY_OF_MONTH field.
EDIT: Actually, I've just noticed that for a change, java.util.Calendar is actually simpler than Joda Time - there's a particular field for it! All you need is:
int weekOfWeekDay = calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH);
From the docs for DAY_OF_WEEK_IN_MONTH:
Field number for get and set indicating the ordinal number of the day of the week within the current month. Together with the DAY_OF_WEEK field, this uniquely specifies a day within a month. Unlike WEEK_OF_MONTH and WEEK_OF_YEAR, this field's value does not depend on getFirstDayOfWeek() or getMinimalDaysInFirstWeek(). DAY_OF_MONTH 1 through 7 always correspond to DAY_OF_WEEK_IN_MONTH 1; 8 through 14 correspond to DAY_OF_WEEK_IN_MONTH 2, and so on.
I think I'd probably still use the Joda Time version because it's just a much nicer API all round, but if you're forced to use Calendar, at least you can do this in one shot.
I have a datepicker where the user selects a date and then a checkbox on what type of period he wants to get the date from. For example:
User selects the 1. of November and selects the checkbox "Month" in this case the end date will be increased by 1 and even if this sound simple enough its slowly starting to annoy me alot!
The problem is that Java doesnt have a great date object that works for this kind of thing so i thought that i would use Calendar but it isnt easy to increment a calendar date take for instance the following example:
endDate.set(startDate.YEAR, startDate.MONTH+1, startDate.DATE);
in theory this would increment the month by one being one larger than the start date. This works in about 90 % of the months EXECPT from December if you increase the month by 1 in December then the integer month return 13 same thing happens for startDate.DATE; and startDate.Year;
My question is isnt there an easier way to do this? i could make a ton of If sentences but i really think that it is kinda redundant.
Use add method of java.util.Calendar.
endDate.set(startDate.YEAR, startDate.MONTH, startDate.DATE);
if(some_condition) {
endDate.add(Calendar.MONTH, 1);
}
You can use Calendar.add() to add values to the calendar value, e.g. Calendar.add(Calendar.MONTH, 1) this adds one month and takes into account that January is after December.
The standard recomendation here is to look at Joda-Time (see here for more info). It's a much more consistent/capable API with none of the threading issues that plague the standard Java date/formatting APIs and as such is widely used and accepted.
In terms of what you want above, I would suggest something like:
LocalDate d = ...
LocalDate nd = d.plusMonths(1);
The above will correctly handle month/year rollovers.
I want to find the day of the week in java without the use of date and other methods that do it on theirselves.I can find the daydifference between 2 dates but I cant understand how I can find which day of the week that specific date is.
If you can find the day difference between two days, then just use the mod operator.
For instance, if you know that day1 = Monday, and you want to find which day it is after 701 days, it is Monday + 701 % 7 = Monday + 1 = Tuesday.
There are formulas for figuring out what day of the week a particular day is on:
http://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Purely_mathematical_methods
The approach you've chosen seems extremely complicated and error prone.
I suggest creating your own class named Date.
A date will contain a month, day, and year and will know how to subtract or add days.
It should also be able to determine if it is equal to, before, or after another date.
You should use an array of ints to represent the number of days in each month.
This array can be a private static field of your Date class.
Then you can create an instance of your class that represents date2 and subtract one day at a time until it equals date1.
You can use a similar approach to determine the day of the week by comparing the input dates to a base date with a known day of week.
I'm certain this is what your instructor intended for this assignment.
This will teach you a valuable lesson:
Take advantage of objects to use encapsulation in stead of using a bunch of if statements.