0
# Legacy Conversion
1
2
Bidirectional conversion methods between legacy `java.util.Date/Calendar/TimeZone` types and modern `java.time` API types, enabling smooth migration and interoperability between old and new date/time systems.
3
4
## Capabilities
5
6
### Calendar to java.time Conversions
7
8
Converting `java.util.Calendar` objects to modern `java.time` types.
9
10
```groovy { .api }
11
/**
12
* Converts the Calendar to a corresponding LocalDate.
13
*/
14
LocalDate toLocalDate(Calendar self)
15
16
/**
17
* Converts the Calendar to a corresponding LocalTime.
18
*/
19
LocalTime toLocalTime(Calendar self)
20
21
/**
22
* Converts the Calendar to a corresponding LocalDateTime.
23
*/
24
LocalDateTime toLocalDateTime(Calendar self)
25
26
/**
27
* Converts the Calendar to a corresponding ZonedDateTime.
28
*/
29
ZonedDateTime toZonedDateTime(Calendar self)
30
31
/**
32
* Converts the Calendar to a corresponding OffsetDateTime.
33
*/
34
OffsetDateTime toOffsetDateTime(Calendar self)
35
36
/**
37
* Converts the Calendar to a corresponding OffsetTime.
38
*/
39
OffsetTime toOffsetTime(Calendar self)
40
41
/**
42
* Converts the Calendar to a corresponding Year.
43
*/
44
Year toYear(Calendar self)
45
46
/**
47
* Converts the Calendar to a corresponding Month.
48
*/
49
Month toMonth(Calendar self)
50
51
/**
52
* Converts the Calendar to a corresponding YearMonth.
53
*/
54
YearMonth toYearMonth(Calendar self)
55
56
/**
57
* Converts the Calendar to a corresponding MonthDay.
58
*/
59
MonthDay toMonthDay(Calendar self)
60
61
/**
62
* Converts the Calendar to a corresponding DayOfWeek.
63
*/
64
DayOfWeek toDayOfWeek(Calendar self)
65
66
/**
67
* Returns the ZoneId of the Calendar's timezone.
68
*/
69
ZoneId getZoneId(Calendar self)
70
71
/**
72
* Returns the ZoneOffset of the Calendar's timezone.
73
*/
74
ZoneOffset getZoneOffset(Calendar self)
75
76
/**
77
* Converts the Calendar to an Instant.
78
*/
79
Instant toInstant(Calendar self)
80
```
81
82
**Usage Examples:**
83
84
```groovy
85
import java.time.*
86
import java.util.*
87
88
// Create a Calendar for testing
89
def calendar = Calendar.getInstance()
90
calendar.set(2024, Calendar.DECEMBER, 25, 14, 30, 45)
91
calendar.set(Calendar.MILLISECOND, 123)
92
93
// Basic temporal conversions
94
def localDate = calendar.toLocalDate() // 2024-12-25
95
def localTime = calendar.toLocalTime() // 14:30:45.123
96
def localDateTime = calendar.toLocalDateTime() // 2024-12-25T14:30:45.123
97
98
println "LocalDate: ${localDate}"
99
println "LocalTime: ${localTime}"
100
println "LocalDateTime: ${localDateTime}"
101
102
// Timezone-aware conversions
103
def zonedDateTime = calendar.toZonedDateTime() // Includes timezone
104
def offsetDateTime = calendar.toOffsetDateTime() // Fixed offset
105
def offsetTime = calendar.toOffsetTime() // Time with offset
106
107
println "ZonedDateTime: ${zonedDateTime}"
108
println "OffsetDateTime: ${offsetDateTime}"
109
110
// Component extractions
111
def year = calendar.toYear() // Year 2024
112
def month = calendar.toMonth() // Month DECEMBER
113
def yearMonth = calendar.toYearMonth() // 2024-12
114
def monthDay = calendar.toMonthDay() // --12-25
115
def dayOfWeek = calendar.toDayOfWeek() // Day of week
116
117
println "Year: ${year}, Month: ${month}, YearMonth: ${yearMonth}"
118
println "MonthDay: ${monthDay}, DayOfWeek: ${dayOfWeek}"
119
120
// Timezone information
121
def zoneId = calendar.zoneId // System default or calendar's zone
122
def zoneOffset = calendar.zoneOffset // Offset from UTC
123
124
println "ZoneId: ${zoneId}, ZoneOffset: ${zoneOffset}"
125
126
// Instant conversion
127
def instant = calendar.toInstant() // Point in time
128
println "Instant: ${instant}"
129
```
130
131
### Date to java.time Conversions
132
133
Converting `java.util.Date` objects to modern `java.time` types.
134
135
```groovy { .api }
136
/**
137
* Converts the Date to a corresponding LocalDate.
138
*/
139
LocalDate toLocalDate(Date self)
140
141
/**
142
* Converts the Date to a corresponding LocalTime.
143
*/
144
LocalTime toLocalTime(Date self)
145
146
/**
147
* Converts the Date to a corresponding LocalDateTime.
148
*/
149
LocalDateTime toLocalDateTime(Date self)
150
151
/**
152
* Converts the Date to a corresponding ZonedDateTime.
153
*/
154
ZonedDateTime toZonedDateTime(Date self)
155
156
/**
157
* Converts the Date to a corresponding OffsetDateTime.
158
*/
159
OffsetDateTime toOffsetDateTime(Date self)
160
161
/**
162
* Converts the Date to a corresponding OffsetTime.
163
*/
164
OffsetTime toOffsetTime(Date self)
165
166
/**
167
* Converts the Date to a corresponding Year.
168
*/
169
Year toYear(Date self)
170
171
/**
172
* Converts the Date to a corresponding Month.
173
*/
174
Month toMonth(Date self)
175
176
/**
177
* Converts the Date to a corresponding YearMonth.
178
*/
179
YearMonth toYearMonth(Date self)
180
181
/**
182
* Converts the Date to a corresponding MonthDay.
183
*/
184
MonthDay toMonthDay(Date self)
185
186
/**
187
* Converts the Date to a corresponding DayOfWeek.
188
*/
189
DayOfWeek toDayOfWeek(Date self)
190
191
/**
192
* Returns the ZoneId associated with the Date (typically system default).
193
*/
194
ZoneId getZoneId(Date self)
195
196
/**
197
* Returns the ZoneOffset associated with the Date (typically system default).
198
*/
199
ZoneOffset getZoneOffset(Date self)
200
```
201
202
**Usage Examples:**
203
204
```groovy
205
import java.time.*
206
import java.util.*
207
208
// Create a Date for testing
209
def date = new Date(124, 11, 25, 14, 30, 45) // Note: Year is years since 1900
210
211
// Basic temporal conversions
212
def localDate = date.toLocalDate() // Extract date portion
213
def localTime = date.toLocalTime() // Extract time portion
214
def localDateTime = date.toLocalDateTime() // Date and time
215
216
println "From Date - LocalDate: ${localDate}, LocalTime: ${localTime}"
217
println "LocalDateTime: ${localDateTime}"
218
219
// Timezone-aware conversions (using system default timezone)
220
def zonedDateTime = date.toZonedDateTime()
221
def offsetDateTime = date.toOffsetDateTime()
222
def offsetTime = date.toOffsetTime()
223
224
println "ZonedDateTime: ${zonedDateTime}"
225
println "OffsetDateTime: ${offsetDateTime}"
226
227
// Component extractions
228
def year = date.toYear()
229
def month = date.toMonth()
230
def yearMonth = date.toYearMonth()
231
def monthDay = date.toMonthDay()
232
def dayOfWeek = date.toDayOfWeek()
233
234
println "Components - Year: ${year}, Month: ${month}"
235
println "YearMonth: ${yearMonth}, MonthDay: ${monthDay}, DayOfWeek: ${dayOfWeek}"
236
237
// Timezone information (based on system default)
238
def zoneId = date.zoneId
239
def zoneOffset = date.zoneOffset
240
241
println "ZoneId: ${zoneId}, ZoneOffset: ${zoneOffset}"
242
243
// Convert to Instant (already available in Date)
244
def instant = date.toInstant()
245
println "Instant: ${instant}"
246
```
247
248
### java.time to Legacy Conversions
249
250
Converting modern `java.time` types back to legacy `java.util.Date/Calendar` types.
251
252
```groovy { .api }
253
/**
254
* Converts LocalDate to java.util.Date (time portion cleared).
255
*/
256
Date toDate(LocalDate self)
257
258
/**
259
* Converts LocalTime to java.util.Date (using today's date).
260
*/
261
Date toDate(LocalTime self)
262
263
/**
264
* Converts LocalDateTime to java.util.Date.
265
*/
266
Date toDate(LocalDateTime self)
267
268
/**
269
* Converts Instant to java.util.Date.
270
*/
271
Date toDate(Instant self)
272
273
/**
274
* Converts ZonedDateTime to java.util.Date.
275
*/
276
Date toDate(ZonedDateTime self)
277
278
/**
279
* Converts OffsetDateTime to java.util.Date.
280
*/
281
Date toDate(OffsetDateTime self)
282
283
/**
284
* Converts OffsetTime to java.util.Date.
285
*/
286
Date toDate(OffsetTime self)
287
288
/**
289
* Converts LocalDate to java.util.Calendar (time portion cleared).
290
*/
291
Calendar toCalendar(LocalDate self)
292
293
/**
294
* Converts LocalTime to java.util.Calendar (using today's date).
295
*/
296
Calendar toCalendar(LocalTime self)
297
298
/**
299
* Converts LocalDateTime to java.util.Calendar.
300
*/
301
Calendar toCalendar(LocalDateTime self)
302
303
/**
304
* Converts Instant to java.util.Calendar.
305
*/
306
Calendar toCalendar(Instant self)
307
308
/**
309
* Converts ZonedDateTime to java.util.Calendar.
310
*/
311
Calendar toCalendar(ZonedDateTime self)
312
313
/**
314
* Converts OffsetDateTime to java.util.Calendar.
315
*/
316
Calendar toCalendar(OffsetDateTime self)
317
318
/**
319
* Converts OffsetTime to java.util.Calendar.
320
*/
321
Calendar toCalendar(OffsetTime self)
322
```
323
324
**Usage Examples:**
325
326
```groovy
327
import java.time.*
328
import java.util.*
329
330
// Convert LocalDate to legacy types
331
def localDate = LocalDate.of(2024, 12, 25)
332
def dateFromLocalDate = localDate.toDate() // Date with time at start of day
333
def calendarFromLocalDate = localDate.toCalendar() // Calendar with time cleared
334
335
println "LocalDate to Date: ${dateFromLocalDate}"
336
println "LocalDate to Calendar: ${calendarFromLocalDate.time}"
337
338
// Convert LocalTime to legacy types (uses today's date)
339
def localTime = LocalTime.of(14, 30, 45)
340
def dateFromLocalTime = localTime.toDate() // Today's date with specified time
341
def calendarFromLocalTime = localTime.toCalendar() // Today's date with specified time
342
343
println "LocalTime to Date: ${dateFromLocalTime}"
344
345
// Convert LocalDateTime to legacy types
346
def localDateTime = LocalDateTime.of(2024, 12, 25, 14, 30, 45)
347
def dateFromDateTime = localDateTime.toDate()
348
def calendarFromDateTime = localDateTime.toCalendar()
349
350
println "LocalDateTime to Date: ${dateFromDateTime}"
351
println "Calendar year: ${calendarFromDateTime.get(Calendar.YEAR)}"
352
353
// Convert timezone-aware types
354
def zonedDateTime = ZonedDateTime.of(2024, 12, 25, 14, 30, 45, 0, ZoneId.of('America/New_York'))
355
def dateFromZoned = zonedDateTime.toDate() // Adjusted to system timezone
356
def calendarFromZoned = zonedDateTime.toCalendar() // Preserves original timezone
357
358
println "ZonedDateTime to Date: ${dateFromZoned}"
359
println "Calendar timezone: ${calendarFromZoned.timeZone.id}"
360
361
// Convert Instant to legacy types
362
def instant = Instant.now()
363
def dateFromInstant = instant.toDate()
364
def calendarFromInstant = instant.toCalendar() // GMT timezone
365
366
println "Instant to Date: ${dateFromInstant}"
367
println "Instant to Calendar: ${calendarFromInstant.time}"
368
```
369
370
### TimeZone Conversions
371
372
Converting between `java.util.TimeZone` and `java.time` timezone types.
373
374
```groovy { .api }
375
/**
376
* Converts TimeZone to ZoneOffset using current time.
377
*/
378
ZoneOffset toZoneOffset(TimeZone self)
379
380
/**
381
* Converts TimeZone to ZoneOffset at the specified instant.
382
*/
383
ZoneOffset toZoneOffset(TimeZone self, Instant instant)
384
385
/**
386
* Converts ZoneId to java.util.TimeZone.
387
*/
388
TimeZone toTimeZone(ZoneId self)
389
390
/**
391
* Converts ZoneOffset to java.util.TimeZone.
392
*/
393
TimeZone toTimeZone(ZoneOffset self)
394
```
395
396
**Usage Examples:**
397
398
```groovy
399
import java.time.*
400
import java.util.*
401
402
// TimeZone to ZoneOffset conversion
403
def estTimeZone = TimeZone.getTimeZone('America/New_York')
404
def currentOffset = estTimeZone.toZoneOffset() // Current offset
405
def summerOffset = estTimeZone.toZoneOffset(Instant.parse('2024-07-01T00:00:00Z')) // Summer offset
406
def winterOffset = estTimeZone.toZoneOffset(Instant.parse('2024-01-01T00:00:00Z')) // Winter offset
407
408
println "EST Current offset: ${currentOffset}"
409
println "EST Summer offset: ${summerOffset}" // Likely -04:00 (EDT)
410
println "EST Winter offset: ${winterOffset}" // Likely -05:00 (EST)
411
412
// ZoneId to TimeZone conversion
413
def zoneId = ZoneId.of('Europe/London')
414
def timeZone = zoneId.toTimeZone()
415
416
println "ZoneId to TimeZone: ${timeZone.id}"
417
418
// ZoneOffset to TimeZone conversion
419
def offset = ZoneOffset.ofHours(5)
420
def offsetTimeZone = offset.toTimeZone() // GMT+05:00
421
422
println "ZoneOffset to TimeZone: ${offsetTimeZone.id}"
423
424
// Complex timezone handling
425
def utcZone = ZoneId.of('UTC')
426
def utcTimeZone = utcZone.toTimeZone()
427
def utcOffset = utcTimeZone.toZoneOffset()
428
429
println "UTC roundtrip: ${utcZone} -> ${utcTimeZone.id} -> ${utcOffset}"
430
```
431
432
### Round-trip Conversion Examples
433
434
Demonstrating bidirectional conversion between legacy and modern types.
435
436
**Usage Examples:**
437
438
```groovy
439
import java.time.*
440
import java.util.*
441
442
// Date -> LocalDateTime -> Date roundtrip
443
def originalDate = new Date()
444
def localDateTime = originalDate.toLocalDateTime()
445
def convertedBackDate = localDateTime.toDate()
446
447
println "Date roundtrip: ${originalDate} -> ${localDateTime} -> ${convertedBackDate}"
448
println "Equal: ${originalDate.time == convertedBackDate.time}" // May differ by milliseconds
449
450
// Calendar -> ZonedDateTime -> Calendar roundtrip
451
def originalCalendar = Calendar.getInstance()
452
originalCalendar.set(2024, Calendar.DECEMBER, 25, 14, 30, 45)
453
originalCalendar.set(Calendar.MILLISECOND, 0) // Clear milliseconds for cleaner comparison
454
455
def zonedDateTime = originalCalendar.toZonedDateTime()
456
def convertedBackCalendar = zonedDateTime.toCalendar()
457
458
println "Calendar roundtrip preserves values:"
459
println "Original year: ${originalCalendar.get(Calendar.YEAR)}, converted: ${convertedBackCalendar.get(Calendar.YEAR)}"
460
println "Original month: ${originalCalendar.get(Calendar.MONTH)}, converted: ${convertedBackCalendar.get(Calendar.MONTH)}"
461
println "Original day: ${originalCalendar.get(Calendar.DAY_OF_MONTH)}, converted: ${convertedBackCalendar.get(Calendar.DAY_OF_MONTH)}"
462
463
// TimeZone handling in conversions
464
def specificTimeZone = TimeZone.getTimeZone('Asia/Tokyo')
465
def japanCalendar = Calendar.getInstance(specificTimeZone)
466
japanCalendar.set(2024, Calendar.DECEMBER, 25, 14, 30, 45)
467
468
def japanZoned = japanCalendar.toZonedDateTime()
469
def backToCalendar = japanZoned.toCalendar()
470
471
println "Timezone preserved: ${japanCalendar.timeZone.id} -> ${japanZoned.zone} -> ${backToCalendar.timeZone.id}"
472
```
473
474
### Migration Strategies
475
476
Practical approaches for migrating from legacy to modern date/time APIs.
477
478
**Usage Examples:**
479
480
```groovy
481
import java.time.*
482
import java.util.*
483
484
// Legacy code simulation
485
class LegacyDateService {
486
Date createAppointment(Date date, int durationMinutes) {
487
def calendar = Calendar.getInstance()
488
calendar.time = date
489
calendar.add(Calendar.MINUTE, durationMinutes)
490
return calendar.time
491
}
492
493
boolean isWorkingDay(Date date) {
494
def calendar = Calendar.getInstance()
495
calendar.time = date
496
def dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)
497
return dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY
498
}
499
}
500
501
// Modern equivalent using conversions
502
class ModernDateService {
503
Date createAppointment(Date legacyDate, int durationMinutes) {
504
// Convert to modern API, do work, convert back
505
def localDateTime = legacyDate.toLocalDateTime()
506
def endDateTime = localDateTime.plusMinutes(durationMinutes)
507
return endDateTime.toDate()
508
}
509
510
boolean isWorkingDay(Date legacyDate) {
511
// Convert to modern API for easier day-of-week checking
512
def dayOfWeek = legacyDate.toDayOfWeek()
513
return dayOfWeek.isWeekday() // Uses modern extension method
514
}
515
}
516
517
// Wrapper for gradual migration
518
class DateWrapper {
519
private final LocalDateTime dateTime
520
521
DateWrapper(Date legacyDate) {
522
this.dateTime = legacyDate.toLocalDateTime()
523
}
524
525
DateWrapper(LocalDateTime modernDateTime) {
526
this.dateTime = modernDateTime
527
}
528
529
// Provide both legacy and modern access
530
Date toLegacyDate() { dateTime.toDate() }
531
LocalDateTime toModernDateTime() { dateTime }
532
533
// Modern functionality
534
DateWrapper plusDays(int days) {
535
new DateWrapper(dateTime.plusDays(days))
536
}
537
538
String format(String pattern) {
539
dateTime.format(pattern)
540
}
541
}
542
543
// Usage examples
544
def legacyService = new LegacyDateService()
545
def modernService = new ModernDateService()
546
547
def testDate = new Date()
548
def appointment1 = legacyService.createAppointment(testDate, 60)
549
def appointment2 = modernService.createAppointment(testDate, 60)
550
551
println "Legacy result: ${appointment1}"
552
println "Modern result: ${appointment2}"
553
println "Results equal: ${appointment1.time == appointment2.time}"
554
555
// Wrapper usage
556
def wrapper = new DateWrapper(testDate)
557
def futureWrapper = wrapper.plusDays(7)
558
def formatted = futureWrapper.format('yyyy-MM-dd HH:mm:ss')
559
560
println "Wrapped date + 7 days: ${formatted}"
561
println "Back to legacy: ${futureWrapper.toLegacyDate()}"
562
```