Add months to a calendar without modifying the original instance

0

I'm implementing a system in which I wrap a specific date in a variable of type Calendar and then I need to manipulate it.

I would like to take the value of a few months added:

Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH,4);

What I'd like is to get that date added to another variable, which does not affect Calendar since it's a Singleton class.

    
asked by anonymous 29.12.2018 / 04:16

1 answer

2

The fact that getInstance() is static does not mean that Calendar is a Singleton .

Singleton means that only one instance of the class in the JVM. But getInstance() always returns a new instance:

Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
System.out.println(c1 == c2); // false

The above code prints false , since c1 and c2 are not the same instance. Note that although getInstance() is static, a new instance is always returned.

In this case, the getInstance() method is working with a static factory method . Just because there is a static method that returns an instance, it does not necessarily mean that this instance will be a singleton .

How to Copy an Instance

The detail is that getInstance() returns a Calendar that corresponds to the current date and time. That is, c1 and c2 will not have exactly the same values.

If you want to get a new instance with the same values as the original, just copy it using the clone() . Then you can change the clone at will, without modifying the original:

Calendar calendar = Calendar.getInstance();

// criar outro Calendar, com o mesmo valor do original
Calendar clone = (Calendar) calendar.clone();
clone.add(Calendar.MONTH, 4); // somar 4 meses

With this, the clone can be changed as needed, and the original% w / w will not change its value.

calendar

There was an answer where the questioner said that he had found a solution, directly using GregorianCalendar . The answer was deleted, but anyway I left this additional explanation as a complement.

GregorianCalendar is a subclass of GregorianCalendar , and it's okay to use it directly, if so desired. The detail is that you were probably already using this class without knowing.

This happens because Calendar is an abstract class, which means that it is not possible to instantiate directly with Calendar . So new Calendar() actually returns some subclass of getInstance() , based on the JVM default Calendar . . And in the vast majority of cases * (for almost all locales), the return is Locale :

Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getClass()); // class java.util.GregorianCalendar

Of course you can use GregorianCalendar directly if you want. But you can also continue using GregorianCalendar with no problems, and if you want a getInstance() not to be modified, make copies of it Calendar .

* From what I saw in the Android documentation , clone() seems to be the only native subclass. However, in JDK there are other implementations, so some local may return different subclasses .

GregorianCalendar

From the API level 26 you can also use the package java.time . This new date API is much higher than java.time and Date , and in my opinion, it's worth migrating your code to using it.

An interesting detail that would help in your case is that all classes are immutable, so any operations (such as adding months to a date) always return a new instance. An example with Calendar :

LocalDate hoje = LocalDate.now(); // data atual
// somar 4 meses (retorna uma nova instância)
LocalDate maisQuatroMeses = hoje.plusMonths(4);

java.time.LocalDate (and all other methods for adding / subtracting days / months / years) returns a new instance, then the variable plusMonths() will remain the same (there is no need to clone the instance, as we did with hoje ).

Another detail is that in this API there are several different classes to represent dates and times, unlike the previous API, which only has Calendar and Date .

For example, Calendar represents only the date (day, month, and year). There is also LocalDate , to represent hours (only hour, minute, second, and fractions of a second), LocalTime for date and time, LocalDateTime to handle time zones, etc. I suggest you look at the Oracle tutorial and this question for more details on this API.

    
29.12.2018 / 11:42