Skip to content

Commit c94ba15

Browse files
committed
calendar date conversions
see issue #885
1 parent c7884f7 commit c94ba15

File tree

3 files changed

+188
-25
lines changed

3 files changed

+188
-25
lines changed

base/src/main/java/net/time4j/engine/CalendarDate.java

Lines changed: 113 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* -----------------------------------------------------------------------
3-
* Copyright © 2013-2018 Meno Hochschild, <http://www.menodata.de/>
3+
* Copyright © 2013-2021 Meno Hochschild, <http://www.menodata.de/>
44
* -----------------------------------------------------------------------
55
* This file (CalendarDate.java) is part of project Time4J.
66
*
@@ -21,6 +21,8 @@
2121

2222
package net.time4j.engine;
2323

24+
import java.time.chrono.ChronoLocalDate;
25+
2426

2527
/**
2628
* <p>Represents a general calendar date. </p>
@@ -88,12 +90,7 @@ default <T extends Calendrical<?, T>> T transform(Chronology<T> target) {
8890

8991
long utcDays = this.getDaysSinceEpochUTC();
9092
CalendarSystem<T> calsys = target.getCalendarSystem();
91-
92-
if ((calsys.getMinimumSinceUTC() > utcDays) || (calsys.getMaximumSinceUTC() < utcDays)) {
93-
throw new ArithmeticException("Cannot transform <" + utcDays + "> to: " + target.getChronoType().getName());
94-
} else {
95-
return calsys.transform(utcDays);
96-
}
93+
return DateTools.convert(utcDays, calsys, target);
9794

9895
}
9996

@@ -137,12 +134,7 @@ default <T extends CalendarVariant<T>> T transform(
137134

138135
long utcDays = this.getDaysSinceEpochUTC();
139136
CalendarSystem<T> calsys = target.getCalendarSystem(variant);
140-
141-
if ((calsys.getMinimumSinceUTC() > utcDays) || (calsys.getMaximumSinceUTC() < utcDays)) {
142-
throw new ArithmeticException("Cannot transform <" + utcDays + "> to: " + target.getChronoType().getName());
143-
} else {
144-
return calsys.transform(utcDays);
145-
}
137+
return DateTools.convert(utcDays, calsys, target);
146138

147139
}
148140

@@ -232,12 +224,7 @@ default <T extends Calendrical<?, T>> T transform(Class<T> target) {
232224

233225
long utcDays = this.getDaysSinceEpochUTC();
234226
CalendarSystem<T> calsys = chronology.getCalendarSystem();
235-
236-
if ((calsys.getMinimumSinceUTC() > utcDays) || (calsys.getMaximumSinceUTC() < utcDays)) {
237-
throw new ArithmeticException("Cannot transform <" + utcDays + "> to: " + ref);
238-
} else {
239-
return calsys.transform(utcDays);
240-
}
227+
return DateTools.convert(utcDays, calsys, chronology);
241228

242229
}
243230

@@ -292,12 +279,7 @@ default <T extends CalendarVariant<T>> T transform(
292279

293280
long utcDays = this.getDaysSinceEpochUTC();
294281
CalendarSystem<T> calsys = chronology.getCalendarSystem(variant);
295-
296-
if ((calsys.getMinimumSinceUTC() > utcDays) || (calsys.getMaximumSinceUTC() < utcDays)) {
297-
throw new ArithmeticException("Cannot transform <" + utcDays + "> to: " + ref);
298-
} else {
299-
return calsys.transform(utcDays);
300-
}
282+
return DateTools.convert(utcDays, calsys, chronology);
301283

302284
}
303285

@@ -345,4 +327,110 @@ default <T extends CalendarVariant<T>> T transform(
345327

346328
}
347329

330+
/**
331+
* <p>Converts the calendar date corresponding to {@code ChronoLocalDate}
332+
* in given target chronology and variant. </p>
333+
*
334+
* @param <T> type of target chronology
335+
* @param threeten the {@code ChronoLocalDate} to be converted
336+
* @param target chronology given date shall be converted to
337+
* @param variantSource source of desired calendar variant
338+
* @return converted date of target type T
339+
* @throws ChronoException if the variant of given source is not recognized
340+
* @throws ArithmeticException in case of numerical overflow
341+
* @since 5.8
342+
*/
343+
/*[deutsch]
344+
* <p>Konvertiert das gegebene Kalenderdatum entsprechend {@code ChronoLocalDate}
345+
* zur angegebenen Zielchronologie und Variante. </p>
346+
*
347+
* @param <T> type of target chronology
348+
* @param threeten the {@code ChronoLocalDate} to be converted
349+
* @param target chronology given date shall be converted to
350+
* @param variantSource source of desired calendar variant
351+
* @return converted date of target type T
352+
* @throws ChronoException if the variant of given source is not recognized
353+
* @throws ArithmeticException in case of numerical overflow
354+
* @since 5.8
355+
*/
356+
static <T extends CalendarVariant<T>> T from(
357+
ChronoLocalDate threeten,
358+
CalendarFamily<T> target,
359+
VariantSource variantSource
360+
) {
361+
362+
return from(threeten, target, variantSource.getVariant());
363+
364+
}
365+
366+
/**
367+
* <p>Converts the calendar date corresponding to {@code ChronoLocalDate}
368+
* in given target chronology and variant. </p>
369+
*
370+
* @param <T> type of target chronology
371+
* @param threeten the {@code ChronoLocalDate} to be converted
372+
* @param target chronology given date shall be converted to
373+
* @param variant desired calendar variant
374+
* @return converted date of target type T
375+
* @throws ChronoException if the variant of given source is not recognized
376+
* @throws ArithmeticException in case of numerical overflow
377+
* @since 5.8
378+
*/
379+
/*[deutsch]
380+
* <p>Konvertiert das gegebene Kalenderdatum entsprechend {@code ChronoLocalDate}
381+
* zur angegebenen Zielchronologie und Variante. </p>
382+
*
383+
* @param <T> type of target chronology
384+
* @param threeten the {@code ChronoLocalDate} to be converted
385+
* @param target chronology given date shall be converted to
386+
* @param variant desired calendar variant
387+
* @return converted date of target type T
388+
* @throws ChronoException if the variant of given source is not recognized
389+
* @throws ArithmeticException in case of numerical overflow
390+
* @since 5.8
391+
*/
392+
static <T extends CalendarVariant<T>> T from(
393+
ChronoLocalDate threeten,
394+
CalendarFamily<T> target,
395+
String variant
396+
) {
397+
398+
long utcDays = EpochDays.UTC.transform(threeten.toEpochDay(), EpochDays.UNIX);
399+
CalendarSystem<T> calsys = target.getCalendarSystem(variant);
400+
return DateTools.convert(utcDays, calsys, target);
401+
402+
}
403+
404+
/**
405+
* <p>Converts the calendar date corresponding to {@code ChronoLocalDate} in given target chronology. </p>
406+
*
407+
* @param <T> type of target chronology
408+
* @param threeten the {@code ChronoLocalDate} to be converted
409+
* @param target chronology given date shall be converted to
410+
* @return converted date of target type T
411+
* @throws ArithmeticException in case of numerical overflow
412+
* @since 5.8
413+
*/
414+
/*[deutsch]
415+
* <p>Konvertiert das gegebene Kalenderdatum entsprechend {@code ChronoLocalDate}
416+
* zur angegebenen Zielchronologie. </p>
417+
*
418+
* @param <T> type of target chronology
419+
* @param threeten the {@code ChronoLocalDate} to be converted
420+
* @param target chronology given date shall be converted to
421+
* @return converted date of target type T
422+
* @throws ArithmeticException in case of numerical overflow
423+
* @since 5.8
424+
*/
425+
static <T extends Calendrical<?, T>> T from(
426+
ChronoLocalDate threeten,
427+
Chronology<T> target
428+
) {
429+
430+
long utcDays = EpochDays.UTC.transform(threeten.toEpochDay(), EpochDays.UNIX);
431+
CalendarSystem<T> calsys = target.getCalendarSystem();
432+
return DateTools.convert(utcDays, calsys, target);
433+
434+
}
435+
348436
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* -----------------------------------------------------------------------
3+
* Copyright © 2013-2021 Meno Hochschild, <http://www.menodata.de/>
4+
* -----------------------------------------------------------------------
5+
* This file (DateTools.java) is part of project Time4J.
6+
*
7+
* Time4J is free software: You can redistribute it and/or modify it
8+
* under the terms of the GNU Lesser General Public License as published
9+
* by the Free Software Foundation, either version 2.1 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* Time4J is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with Time4J. If not, see <http://www.gnu.org/licenses/>.
19+
* -----------------------------------------------------------------------
20+
*/
21+
22+
package net.time4j.engine;
23+
24+
25+
/**
26+
* Small helper class due to lack of private interface methods in Java 8.
27+
*
28+
* @author Meno Hochschild
29+
* @since 5.8
30+
*/
31+
final class DateTools {
32+
33+
//~ Konstruktoren -----------------------------------------------------
34+
35+
private DateTools() {
36+
// no instantiation
37+
}
38+
39+
//~ Methoden ----------------------------------------------------------
40+
41+
// conversion routine used by interface CalendarDate
42+
static <T> T convert(
43+
long utcDays,
44+
CalendarSystem<T> calsys,
45+
Chronology<T> target
46+
) {
47+
48+
if ((calsys.getMinimumSinceUTC() > utcDays) || (calsys.getMaximumSinceUTC() < utcDays)) {
49+
throw new ArithmeticException("Cannot transform <" + utcDays + "> to: " + target.getChronoType().getName());
50+
} else {
51+
return calsys.transform(utcDays);
52+
}
53+
54+
}
55+
56+
}

base/src/test/java/net/time4j/calendar/HijriMiscellaneousTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.junit.runners.JUnit4;
1818

1919
import java.text.ParseException;
20+
import java.time.chrono.HijrahDate;
2021
import java.time.format.FormatStyle;
2122
import java.util.Locale;
2223

@@ -426,4 +427,22 @@ public void registerExampleData() {
426427
is(PlainDate.of(2028, 5, 20)));
427428
}
428429

430+
@Test
431+
public void genericDateConversion(){
432+
HijrahDate hijri = HijrahDate.of(1436, 9, 29);
433+
assertThat(
434+
CalendarDate.from(
435+
hijri,
436+
HijriCalendar.family(),
437+
() -> HijriCalendar.VARIANT_UMALQURA
438+
),
439+
is(HijriCalendar.ofUmalqura(1436, HijriMonth.RAMADAN, 29)));
440+
assertThat(
441+
CalendarDate.from(
442+
hijri,
443+
PlainDate.axis()
444+
),
445+
is(PlainDate.of(2015, 7, 16)));
446+
}
447+
429448
}

0 commit comments

Comments
 (0)