Why LocalDate doesn't implements Comparable<LocalDate>? - java

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.

Related

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).

Handling classes that violate the 'Liskov substitution principle' using method overloading

Suppose I have the following class:
public class MyClass {
/* Note: Timestamp extends date */
public doSomething(java.sql.Timestamp timestamp){
System.out.println("Timestamp");
...
}
public doSomething(java.util.Date date){
System.out.println("Date");
...
}
}
Suppose that I now exercise my code like this:
MyClass myClass = new MyClass();
Date realDate = new Date();
Timestamp timestamp = new Timestamp(0);
Date casted = new Timestamp(0);
myClass.doSomething(realDate); // prints Date
myClass.doSomething(timestamp); // prints Timestamp
myClass.doSomething(casted); // prints Date!!!!! What?!
The problem that I am having is that since casted is not actually a date, when I use it doesn't work.
Aside: Generally, subclasses not working shouldn't be an issue, however the javadoc for Timestamp says:
Due to the differences between the Timestamp class and the java.util.Date class mentioned above, it is recommended that code not view Timestamp values generically as an instance of java.util.Date. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance.
I know that I could do something like this:
public doSomething(java.util.Date date){
if(date instanceof type){
System.out.println("Timestamp");
...
}
System.out.println("Date");
...
}
But this just seems nasty.
Is there a way to get method overloading of subclasses to work without using giant switch statements?
Edit: In short, it seems like Timestamp breaks the Liskov substitution principle - as pointed out by #Mick Mnemonic.
Yep. Not your bug. It's a design quirk of java.util.Date, java.sql.Date, and Timestamp. (Don't be too hard on them. java.util.Date is twenty years old now; they were still figuring this stuff out when they were designing the API.) There's no great way around it if you work directly with these types.
One approach is to avoid using these classes except where you have to, at the boundary with APIs that require them, and use a better-designed set of date-time types elsewhere. In your data access layer, special-case Timestamp etc using instanceof where necessary. And convert everything to Joda-Time (for Java 7) or java.time/JSR-310 (for Java 8) types for your internal code. (If you actually need nanosecond precision in Java 7, you'll need to roll your own Timestamp object to go with the Joda-Time types. Not hard; just make sure to use composition instead of implementation inheritance like the java.util folks did! :) ) You will probably be happier.

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 ) ;

Developing a simple utility class( like a Date class )in java

I am a college student.
In our college we have to develop a simple Date class in Java similar to the one available in java.util package.
If we do that then what are the methods we can implement in that class,
Since most of the methods are deprecated in original Date class.
I saw the original Date class definitions in java/util/Date.java. Being a beginner to java, I could not understand the concepts of Serializable, Cloneable, Comparable ,and many variables like fasttime.
It will be good if we can implement this date class simply (since we have to develop this code as a test with in 3 hours at lab.)
Whether it is necessary to implement those concepts in a simple Date class.
If I take it as a Project and start developing the whole Date utilities,
then that code will run to many pages
and I cannot finish it with 3 hours for our lab session.
So someone please guide me....
I have doubts about....
Whether it is possible to create a utility class similar to Date class with a simpler implementation.
If we do that, then what are the methods we can implement in that class , since most of the useful methods are deprecated in the original date class.
Thanks in advance.
Serializable means the class can be Serialized to a transportable binary form.
Clonable means the class can be cloned, this is very tricky to get right, mainly because of inheritance and mutability concerns.
Comparable means the class supports being compared to other classes of the same type.
Of these Comparable is the only one that requires any code to function, it is also probably the only one that is any use in your scenario.
Serializable is what is called a Marker Interface it doesn't require any code to cause anything to happen since it doesn't have any methods to implement. It just exists to mark the object as supporting something and another class and check for this interface and do things based on its existence.
Cloneable is something you want to stay away from if at all possible. Cloning objects in Java is not straight forward, has lots of gotchas and generally behaves in the most non-intuitive ways imaginable. If you really want to know about this, learn about this, read this article.
Comparable is very valuable, it lets you compare to like objects to see if one is less than, equal or greater than another. This is a requirement for sorting and Collections classes that support Comparators. Comparators can be thought of as stand alone implementations of Comparable that can be plugged into other classes to control how objects are compared.
java.util.Date is a tricky class, it appears to be a straight forward struct type class with some mutators and convenience methods, but the underlying problem domain for calendar data isn't that simple. Calendar math has lots of exceptional cases. That is why there are so many methods on java.util.Date that are deprecated, they produced wrong behavior in many cases.
For some more code to study, look at this temporal package I developed to wrap the standard Java Calendar with very basic Date, Time and TimeStamp classes, they all just delegate to an instance of Calendar for the actual calcuations.
NOTE: this library code pre-dates JodaTime for those of you that might complain about just not using that library.
You don't have to implement all the interfaces to have a simple working Date class.
I would suggest that you forget about Java's Date class and consider what you think is needed for a date class. For example:
Get/set day of month
Get/set month
Get/set year
Get day of week
toString()
Would give you a pretty good basic date class.
For the sake of completeness, I'll tell you what the interfaces are for. You can decide whether to implement them based on how much you have learned and the assignment's requirements:
Serializable is for saving your object to a stream. You actually don't need to do much work to implement it.
Comparable is for comparing objects (date1.compareTo(date2) should return an integer indicating whether date1 is before, after, or the same as date2).
Clonable is for creating a deep copy of the object.
Since this is a lab project, why don't you list down what kind of function a 'simple' Date class needs and should have. For example, toString() -- returns a string representation of a Data or toMilliSecond() -- returns the number of milliSecond from the reference time.

Categories