Difference between GregorianCalendar class and Calendar class in java? - java

While using both classes I found that for creating an object for respective classes
Like
GregorianCalendar today = new GregorianCalendar ();
Calendar today = Calendar.getInstance();
Why it is so? And what is benefits of using one over another?

In most locales, when you write Calendar.getInstance(), it will create a GregorianCalendar object. But there are a few exceptions. Your locale could be set to give you a JapaneseImperialCalendar or a BuddhistCalendar.
If you really need your Calendar to be a GregorianCalendar, then you can explicitly write new GregorianCalendar(). But it's generally considered better form to let the JVM choose the right kind of Calendar based on the locale. That is, you should write Calendar.getInstance(), and be prepared to deal with the possibility of using one of the other calendar types.
There is no logic in the Calendar class for getInstance() to return one of the other types of calendar, such as those used in Iran or Saudi Arabia.

The Calendar Class is nothing but an Abstract Class.The primary reason for making it abstract is that there are multiple types of Calendars available all over the world.

Related

Why LocalDate doesn't implements Comparable<LocalDate>?

Initial Problem:
In Scala, I would like to use implicit Ordering[T]#Ops to compare two LocalDate.
It just to use "operators" like > instead of isAfter.
It should be just an import: import scala.math.Ordering.Implicits._
Inspection:
Looks like it works with LocalTime and doesn't with LocalDate because LocalTime instead of LocalDate implements Comparable<LocalTime>.
Question:
I wondering,
Why LocalDate implements Comparable<ChronoLocalDate> instead of Comparable<LocalDate>?
LocalDate in fact implements Comparable<ChronoLocalDate> as well as ChronoLocalDate and by implementing those two, every instance of it is of course comparable to another LocalDate instance.
You can have a look at the JavaDocs for LocalDate on Oracle's website.
ChronoLocalDate is an interface that is implemented by different types of calendars in order to make them all comparable to each other. That is because there are JapaneseDate, ThaiBuddhistDate, HijrahDate and at least one more. Totally different calendars that are all comparable to each other, which is great. LocalTime, on the other hand, is just a time representation with different time zones and just doesn't have to go this interface-way to be comparable to time representations of different locales.
To make operators work, you just need another line in addition to the import, defining the desired Ordering (assuming Scala 2.12):
implicit val localDateOrdering: Ordering[LocalDate] = _.compareTo(_)
If you want to use it in many classes, define it in an object and import where necessary.

Should org.joda.time.DateTimeZone be declared as static field in a class instead of creating new instance each time

Should org.joda.time.DateTimeZone be defined as static in a class instead of creating a new instance each time it's needed, specially when we're always using the same time zone.
DateTimeZone is thread-safe and immutable so it does not make sense to create a new instance each time. Is my thinking correct?
To add more details, currently my class creates a DateTimeZone object in the constructor of my class, always for the same time zone, so I thought why not make it static instead of creating a new object each time.
DateTimeZone is thread-safe and immutable, and all subclasses must be as well.
See api
So yes. It can be declared as static field.
Should you do it or not, it depends on your class and overall project design. See here why static fields may be evil.
Yes, I think you can create is as a static field - and the link in #Mike's answer tells you about the possible drawbacks of doing so (like possible problems if you want to test your code in a different timezone and so on).
But if your concerns are about performance and memory usage, I wouldn't worry too much about that. It seems that Joda-Time uses an internal cache of DateTimeZone objects:
DateTimeZone zone = DateTimeZone.forID("Europe/London");
DateTimeZone other = DateTimeZone.forID("Europe/London");
System.out.println(zone == other); // true
The code above prints true, which means that both are the same object.
Of course this is an implementation detail (I'm using Joda-Time 2.9.9) and it's not good to rely on such details as these things can change.
Anyway, if you're sure that this timezone will never change, you can make it static. If there's a possibility of having more than one in the future, don't (I wouldn't).

Some doubts about Java polymorphism applied to the Calendar and GregoriaCalendar case

I have the following doubt.
Into my code I have:
Calendar today = Calendar.getInstance();
where today variable is an instance of Calendar so I can't use methods as isLeapYear() on it.
Doing in this way I can perform this method:
GregorianCalendar today = (GregorianCalendar) Calendar.getInstance();
int currentYear = today.get(Calendar.YEAR);
boolean bisestile = today.isLeapYear(currentYear);
My doubt is: exatly why? I am casting the same result instange returned by Calendar.getInstance() to be a GregorianCalendar.
Reading here: http://tutorials.jenkov.com/java-date-time/java-util-calendar.html
it seems to me to understand that The java.util.Calendar class is abstract so I cannot instantiate it so I think that the Calendar.getInstance() automatically return a GregorianCalendar object that have defined the previous isLeapYear() method.
But I can't use it if the object is defined as a simple Calendar and not as a GregorianCalendar.
I know about polymorphism but how exactly works in this specific case?
I think that putting the reference of a GregorianCalendar object (returned by Calendar.getInstance(), is it true?) into a Calendar (I can do it because Calendar is the super type) I can access only to the methods subset defined for this abstract class and not to all the methods defined for the concrete type.
Is it this reasoning correct or am I missing something?
This is polymorphism. Calendar provides an abstract framework, and subclasses like GregorianCalendar provide implementations. In other contexts, understand that Calendar.getInstance() maybe could return (for instance) a Chinese or a Hebrew calendar depending on the locality and system setup.
If what you really want is a GregorianCalendar explicitly, declare the variable as such.
GregorianCalendar cal = new GregorianCalendar();
The Answer by ControlAltDel is correct.
One of the benefits of Object-Oriented Programming is preventing fragile software that breaks after making some change. One of the ways to accomplish that is where we define an interface with one or more implementations. When other code refers to the interface, we can switch out the implementation without breaking the calling code.
So the general rule is to use the highest level of interface that meets your needs.
Example: Collections
For example in Java Collections, use the Collection interface where it meets your needs.
Collection<String> col = new ArrayList<>() ;
Get more specific only if your code requires the additional methods offered by a more specific interface. Here we use List, a sub-interface of Collection that promises additional methods.
List<String> list = new ArrayList<>() ;
Use the ArrayList as an ArrayList only if absolutely necessary, only if that class offers certain methods you require that are not included in its more general interfaces.
ArrayList<String> list = new ArrayList<>() ;
Later we may decide to replace that ArrayList with a LinkedList. Doing so won't break any code that was expecting a List or Collection but would break any calling code that expected an ArrayList specifically.
List<String> list = new LinkedList<>();
Calendar & GregorianCalendar
Similarly, you should use Calendar wherever possible, rather than GregorianCalendar.
Calendar cal = new GregorianCalendar() ;
But if the code absolutely needs the special features of GregorianCalendar then track the object as a GregorianCalendar as shown in the Answer by ControlAltDel.
GregorianCalendar cal = new GregorianCalendar() ;
You can mix this up, using a more-specific type internally and a more-general type externally. If you only need those special GregorianCalendar features inside your own class, but want to expose the calendar to other classes, you can declare the calendar object as a GregorianCalendar as the private member of your class while returning Calendar from a getter method.
…
private GregorianCalendar gregCal = new GregorianCalendar() ;
…
public Calendar getCalendar() {
return this.gregCal ; // Automatically upcast. Appears to any calling code to be a `Calendar`.
}
P.S. The java.util.Calendar & .GregorianCalendar are part of the troublesome old legacy date-time classes now supplanted by the java.time classes built into Java 8 and later. Avoid these old classes.
If you are in Thailand then your code
GregorianCalendar today = (GregorianCalendar) Calendar.getInstance();
will probably fail by throwing a ClassCastException because Calendar.getInstance() can yield the Thai-Buddhist calendar as default in that country. This use-case indicates a strong warning to use Calendar.getInstance() if you are really sitting in Thailand. And then you cannot make your gregorian-based assumptions when you are going to interprete expressions like calendar.get(Calendar.YEAR) (maybe yielding year values like 2543).
Conclusion: When handling date and time, it is much better NOT to use generic interfaces but to be as concrete as possible. I assume you are only interested into the gregorian calendar, so please use:
GregorianCalendar today = new GregorianCalendar();
By the way, the main designers of new java.time-package in Java-8 have also adopted this view to be as concrete as possible:
Most applications should declare method signatures, fields and
variables as LocalDate, not this interface.
Practically this means: You should avoid types like TemporalAccessor, ChronoLocalDate etc., or in old world: Avoid types like java.util.Calendar in favor of concrete types like GregorianCalendar. Polymorphism is not a very good idea in the world of date and time. The concrete types are too different (sometimes in a very subtile way).

Why is Date better than Calendar for property typing when stuck using the legacy API?

First, please note that this question is not a duplicate of this Question:
Java Date vs Calendar. My question is much more specific. The referenced question asks "what" (or "which"), but I already know the "what" and am asking the "why".
I am on a team working on enhancements to an existing Java project for a client. This Java project uses java 6, and does not have Joda Time as a dependency. After inquiring, it looks like adding Joda Time or upgrading to Java 8 are not options.
So, when it comes to representing date/time as a field in an object, we have to use either Calendar or Date for property typing. The legacy code of this project is littered with Objects that use Calendar to represent date/time fields -- fields that we would never have cause to manipulate (as in add or subtract units of time, etc). I know that this is bad practice, as Calendar is a more complex object, while Date is simpler and would work just as well. (And granted, I know that both are fundamentally wrappers for a long of epoch millis, are mutable, and are poorly designed, but again these are our only two options.)
In other words, an object like this:
public class Reservation {
private Guest guest;
// Set only once, never used for calculations
private Calendar dateReserved;
...
}
Should be this instead:
public class Reservation {
private Guest guest;
// Set only once, never used for calculations
private Date dateReserved;
...
}
I then noticed that when adding new Objects for new features, my team was following the same convention of using Calendar instead of Date. When I brought this up, the reply was that it's better to use Calendar because it can do more and doesn't have all these deprecated methods like Date does.
I know that this reasoning is oversimplified. I also see that this answer to the broader question of usage expresses the same view, namely that Calendar should not be used for property typing. However, the answer doesn't contain much explanation as to why Calendar should not be preferred.
So I already know the "What". But I'm trying to make the case to my team, so my question is, "Why"? Why, when property typing, should Date be preferred to Calendar? What are the disadvantages of using Calendar instead of Date for property typing?
I agree with Jon Skeet's comment regarding calendar systems and time zones, and I think your premise is fundamentally flawed. Dates aren't better than Calendars. If you're never ever ever going to compare times, or never ever ever have two dates in different time zones, then sure, the smaller footprint can be nice, I guess, but at that point, just use longs and Unix timestamps. Calendars are by far the better object model, and after all, if you absolutely need it, you can get a Date object from it.
If you are stuck having to choose between Date and Calendar when property typing:
Use Calendar if either one of these is true:
You need to be able to adjust the date/time after it is initially set
(such as changing the month while leaving the day and hour the same).
You need to be aware of timezone.
Otherwise, use Date for the following reasons:
Expressing your intentions accurately. If you use Calendar, you are implying that you want a certain functionality that you don't actually intend to use (timezones, changing the day or month, etc).
Less hassle with String representations. For example, consider this class:
public class Reservation {
private Guest guest;
private Calendar dateReserved;
#Override
public String toString() {
return String.format("Reservation{guest=%s,dateReserved=\"%s\"}",
guest, dateReserved);
}
}
Now if you print out an instance of this class, you'll get something hideous:
Reservation{guest=Guest{id=17,name="John Smith"},dateReserved="java.util.GregorianCalendar[time=1426707020619,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2015,MONTH=2,WEEK_OF_YEAR=12,WEEK_OF_MONTH=3,DAY_OF_MONTH=18,DAY_OF_YEAR=77,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=0,HOUR_OF_DAY=12,MINUTE=30,SECOND=20,MILLISECOND=619,ZONE_OFFSET=-28800000,DST_OFFSET=3600000]"}
Whereas if you had used Date instead, you'd get this:
Reservation{guest=Guest{id=17,name="John Smith"},dateReserved="Wed Mar 18 12:34:26 PDT 2015"}
So if you use Calendar and you want your toString() to be usable, you would need to call dateReserved.getTime() -- which means you'd need to add a null check. This goes for whether or not you end up using a DateFormat object.
Date is a smaller object, quicker to instantiate and with less overhead.
Date is practically immutable -- meaning that the only way to change a date object is to use deprecated methods. So, as said in point 1, expressing your intentions matters. If your date field should be immutable, don't confuse developers who will touch your code in the future by using Calendar (unless of course you need timezone awareness).
"Date" is a more intuitive name than "Calendar" for the type of a field that represents a single point in time.
Date object has fewer fields and occupies less memory than Calendar object and is also faster to instantiate.

When do I use New to instantiate a class

I am just going through a tutorial and the instructor seemed to gloss over something which didn't make sense
In Java if I am looking to instantiate a new Gregorgian Date Object I would use:
GregorianCalendar gc= new GregorianCalendar (2010,1,14);
but if I am looking to use the Data Format object I would use:
DateFormat df = DateFormat.getDateInstance();
I would really like to understand why dateformat doesn't follow the first way of instantiating the class?
How would I know to lookout in future for a similar gotcha?
You should always consult the API documentation to see how you are to use it.
A new X() always create a new object so if you have multiple places you need it, you end up with multiple X'es which may be inefficient if a single X would do.
The .getDateInstance() call is a Factory that allow the API to decide by itself whether to return the same X even to multiple callers or a new one to each. For very expensive but reusable/sharable objects this is the typical way you get them.
The Calendar API was donated to Java a very long time ago and is not as well designed as could be. These days the typical response to "I have problem X with Calendar and/or java.util.Date" in java is to use the Joda library which is well designed. For new code using Java 8 or later, use the new java.time classes as commented by Basil Bourque.
The short answer is that the core Java API is poorly designed and inconsistent. There's often no good reason for these inconsistencies, you just need to live with them.
More generally, factory methods like DateFormat.getDateInstance() allow the API to select different implementation classes depending on the situation, whereas using a constructor directly means there's no such flexibility.
Incidentally, unless you specifically want a GregorianCalendar, then the recommended method for obtaining one is Calendar.getInstance(), which will return you a GregorianCalendar if your locale is appropriate. Other locales will return different Calendar implementations. This would be consistent with your DateFormat example.
this is because it's an abstract class more info on that can be found here: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
same, look if a class is abstract or not.
The Answer by Thorbjørn Ravn Andersen is correct. Here are some more thoughts.
Avoid legacy date-time classes
GregorianCalendar is one of the terrible date-time classes bundled with the earliest versions of Java, designed by people who did not understand date-time handling.
These classes were years ago supplanted by the modern java.time classes. The GregorianCalendar class is specifically replaced by ZonedDateTime.
Immutable classes
The java.time classes are designed to be immutable, making them thread-safe.
This means you never use new. Instead, call factory methods. Read about the naming conventions on such methods.
Let’s capture the current moment as seen through the wall-clock time used by the people of a particular region (a time zone). We call ZonedDateTime.now to capture the current moment. As you can see in the source code, the constructor of ZonedDateTime is marked private to prevent us from instantiating via new. Internally to that class, the factory method performs the new. You can see for yourself, searching that source code for new ZonedDateTime.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
By the way, if you must use a GregorianCalendar to interoperate with old code not yet updated to java.time, you can convert. See new conversion methods added to the old classes.
ZonedDateTime zdt = myGregCal.toZonedDateTime() ;
…and…
GregorianCalendar myGregCal = GregorianCalendar.from( zdt ) ;

Categories