9

I need to figure out how to create a temporary Calendar object (a copy of a "permanent" calendar that already exists) so that I can manipulate the copy: tempCal.add(unit, value). I need to keep the original calendar object unchanged, so I really don't want to call add(unit, value) on it directly.

Since none of my attempts at creating a copy actually worked, my current ugly hack is to call permanentCal.add(unit, value), display the desired results, then call permanentCal.add (unit, -value) — which just seems, uncool.

Daniel Werner
  • 1,350
  • 16
  • 26
Rich
  • 4,157
  • 5
  • 33
  • 45
  • 1
    FYI, the terribly flawed date-time classes such as [`java.util.Date`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/tutorial/datetime/TOC.html) classes built into Java 8 and later. – Basil Bourque Nov 21 '19 at 02:56

5 Answers5

20

java.util.Calendar has a clone method, you could use that. All data in it is made of primitives, so you will not run into troubles.

Have a look at these answers:

Community
  • 1
  • 1
Alberto Zaccagni
  • 30,779
  • 11
  • 72
  • 106
  • I really can't believe I missed that, and using Eclipse, too -- the damn methods were listed right in front of me... Thanks for the info. – Rich May 22 '13 at 14:14
3

If you want to use time, day, month, week, year etc. for calculation purposes, you can copy using timeInMillis like following:

Calendar calendarCopy = Calendar.getInstance()
calendarCopy.setTimeInMillis(calendarOriginal.getTimeInMillis)
doSomethingWith(calendarCopy)

This way you can have the time, day, month, week, year etc inside the copy.

Yogesh Umesh Vaity
  • 41,009
  • 21
  • 145
  • 105
  • Further use of `Calendar` is ill-advised. That terrible class was supplanted years ago by the *java.time* classes defined in [JSR 310](https://jcp.org/en/jsr/detail?id=310). – Basil Bourque Nov 21 '19 at 03:09
  • @BasilBourque You are right, but we are using it for supporting older versions of Android without using external libraries. `ZonedDateTime` is only supported from Android Oreo onwards. Google is still using `Calendar` in their new samples of Android Architecture Components. – Yogesh Umesh Vaity Nov 21 '19 at 11:40
  • 1
    See [my Answer](https://stackoverflow.com/a/58966675/642706) for details on using a back-port of *java.time* functionality for early Android. There is no need to ever use those wretched `Calendar` or `GregorianCalendar` classes again. – Basil Bourque Nov 21 '19 at 17:29
  • FYI, the back-port includes methods to easily convert back and forth between the legacy and modern classes. So you can continue to interoperate with old code not yet updated to *java.time* while doing all your business logic only with the modern classes. – Basil Bourque Nov 21 '19 at 17:39
2

(Not for Android)

Switch to java 8's immutable LocalDateTime, the successor of Calendar/Date. This API is an immense improvement, may be a bit overwhelming at first.

There a method like minusDays(long) will return a new date. Which makes for thread-safeness and all. For instance being able to share a value without fear of someone altering it.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • 2
    Suggesting the *java.time* classes is correct. But `LocalDateTime` is the wrong particular class. The legacy class `GregorianCalendar` (usually the concrete class behind `Calendar`) was replaced by `ZonedDateTime`. – Basil Bourque Nov 21 '19 at 02:57
  • @BasilBourque totally agree, as Calendar is principally used for a Locale dependent display. ZonedDateTime handles day-time-saving and so on. – Joop Eggen Nov 21 '19 at 09:20
2

java.time.ZonedDateTime

The Calendar class is terrible, as is its usual concrete class, GregorianCalendar. These legacy classes were years ago supplanted by the modern java.time classes, specifically ZonedDateTime.

When encountering a Calendar object, see if it is indeed a GregorianCalendar object. If so, convert using new to…/from… methods added to the old classes.

if( myCal instanceof GregorianCalendar ) {
    GregorianCalendar gc = ( GregorianCalendar ) myCal ;  // Cast to the concrete type.
    ZonedDateTime zdt = gc.toZonedDateTime() ;  // Convert from legacy class to modern class.
}

Immutable objects

The java.time classes wisely use the immutable objects pattern, appropriate to their purpose.

So you do not manipulate individual member fields within an existing object. Instead, you pass a new field value to produce a new object based on the combination of original values and your specific different value. See the with methods.

Adding/subtracting a span of time

In your case, it seems you want to perform addition or subtraction to arrive at a new moment.

Specify a span of time by using:

  • Duration for a scale of hours-minutes-seconds
  • Period for a scale of years-months-days.

Example: Add a few days to get a moment later.

Period p = Period.ofDays( 3 ) ;  
ZonedDateTime threeDaysLater = zdt.plus( p ) ;

For doing this kind of work, you might find handy the Interval and LocalDateRange classes offered by the ThreeTen-Extra library linked below.


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, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

enter image description here

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

Joda-Time

If you want to do this in cool way, use the Joda-Time library.

This very successful third-party open-source date-time framework provided the inspiration for the java.time framework now built into Java 8 and later.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Grzegorz Gajos
  • 2,253
  • 19
  • 26
  • This does sound very cool, actually. How much of a big deal is it include Joda in an Android project?? – Rich May 23 '13 at 15:09
  • 1
    Just add joda jar to `libs/` directory, Joda contains a lot of date/time helpers. However I didn't notice that you're working on android application. Joda library might be overhead for you in this particular case. – Grzegorz Gajos May 23 '13 at 15:24
  • Not a problem, more of an academic question anyway. – Rich Jun 27 '13 at 13:23
  • Google to find some special builds of Joda-Time to address some limitation in Android that makes initial loading slow. – Basil Bourque Oct 03 '15 at 03:20