1
2
3
4
5
6 package dev.metaschema.core.metapath.item.atomic;
7
8 import java.time.LocalDate;
9 import java.time.ZoneOffset;
10 import java.time.ZonedDateTime;
11 import java.time.temporal.ChronoUnit;
12
13 import dev.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
14 import dev.metaschema.core.datatype.object.AmbiguousDate;
15 import dev.metaschema.core.datatype.object.AmbiguousDateTime;
16 import dev.metaschema.core.metapath.function.DateTimeFunctionException;
17 import dev.metaschema.core.metapath.function.InvalidValueForCastFunctionException;
18 import dev.metaschema.core.metapath.item.atomic.impl.DateWithoutTimeZoneItemImpl;
19 import dev.metaschema.core.metapath.type.IAtomicOrUnionType;
20 import dev.metaschema.core.metapath.type.InvalidTypeMetapathException;
21 import dev.metaschema.core.util.ObjectUtils;
22 import edu.umd.cs.findbugs.annotations.NonNull;
23 import edu.umd.cs.findbugs.annotations.Nullable;
24
25
26
27
28
29
30
31
32
33
34 public interface IDateItem extends ICalendarTemporalItem {
35
36
37
38
39
40 @NonNull
41 static IAtomicOrUnionType<IDateItem> type() {
42 return MetaschemaDataTypeProvider.DATE.getItemType();
43 }
44
45 @Override
46 default IAtomicOrUnionType<? extends IDateItem> getType() {
47 return type();
48 }
49
50
51
52
53
54
55
56
57 @NonNull
58 static IDateItem valueOf(@NonNull String value) {
59 try {
60 return valueOf(MetaschemaDataTypeProvider.DATE.parse(value));
61 } catch (IllegalArgumentException ex) {
62 throw new InvalidTypeMetapathException(
63 null,
64 String.format("Invalid date value '%s'. %s",
65 value,
66 ex.getLocalizedMessage()),
67 ex);
68 }
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 @NonNull
87 static IDateItem valueOf(@NonNull ZonedDateTime value, boolean hasTimeZone) {
88 ZonedDateTime truncated = ObjectUtils.notNull(value.truncatedTo(ChronoUnit.DAYS));
89 return hasTimeZone
90 ? IDateWithTimeZoneItem.valueOf(truncated)
91 : valueOf(new AmbiguousDate(truncated, false));
92 }
93
94
95
96
97
98
99
100
101
102
103
104 @NonNull
105 static IDateItem valueOf(@NonNull LocalDate value) {
106 return valueOf(ObjectUtils.notNull(value.atStartOfDay(ZoneOffset.UTC)), false);
107 }
108
109
110
111
112
113
114
115
116 @NonNull
117 static IDateItem valueOf(@NonNull AmbiguousDate value) {
118 return value.hasTimeZone()
119 ? IDateWithTimeZoneItem.valueOf(value.getValue())
120 : new DateWithoutTimeZoneItemImpl(value);
121 }
122
123 @Override
124 default boolean hasDate() {
125 return true;
126 }
127
128 @Override
129 default boolean hasTime() {
130 return false;
131 }
132
133 @Override
134 default int getYear() {
135 return asZonedDateTime().getYear();
136 }
137
138 @Override
139 default int getMonth() {
140 return asZonedDateTime().getMonthValue();
141 }
142
143 @Override
144 default int getDay() {
145 return asZonedDateTime().getDayOfMonth();
146 }
147
148 @Override
149 default int getHour() {
150 return 0;
151 }
152
153 @Override
154 default int getMinute() {
155 return 0;
156 }
157
158 @Override
159 default int getSecond() {
160 return 0;
161 }
162
163 @Override
164 default int getNano() {
165 return 0;
166 }
167
168
169
170
171
172
173 @NonNull
174 default IDateTimeItem asDateTime() {
175 return IDateTimeItem.valueOf(this);
176 }
177
178 @Override
179 @NonNull
180 ZonedDateTime asZonedDateTime();
181
182
183
184
185
186
187 @NonNull
188 default LocalDate asLocalDate() {
189 return ObjectUtils.notNull(asZonedDateTime().toLocalDate());
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 @Override
222 default IDateItem replaceTimezone(@Nullable IDayTimeDurationItem offset) {
223 return offset == null
224 ? hasTimezone()
225 ? valueOf(ObjectUtils.notNull(asZonedDateTime().withZoneSameLocal(ZoneOffset.UTC)), false)
226 : this
227 : hasTimezone()
228 ? valueOf(IDateTimeItem.valueOf(this).replaceTimezone(offset).asZonedDateTime(),
229 true)
230 : valueOf(
231 ObjectUtils.notNull(asZonedDateTime().withZoneSameLocal(offset.asZoneOffset())),
232 true);
233 }
234
235
236
237
238
239
240
241
242
243
244
245 @NonNull
246 static IDateItem cast(@NonNull IAnyAtomicItem item) {
247 IDateItem retval;
248 if (item instanceof IDateItem) {
249 retval = (IDateItem) item;
250 } else if (item instanceof IDateTimeItem) {
251 retval = ((IDateTimeItem) item).asDate();
252 } else if (item instanceof IStringItem || item instanceof IUntypedAtomicItem) {
253 try {
254 retval = valueOf(item.asString());
255 } catch (IllegalStateException | InvalidTypeMetapathException ex) {
256
257 throw new InvalidValueForCastFunctionException(ex);
258 }
259 } else {
260 throw new InvalidValueForCastFunctionException(
261 String.format("Unsupported item type '%s'", item.getClass().getName()));
262 }
263 return retval;
264 }
265
266 @Override
267 default IDateItem castAsType(IAnyAtomicItem item) {
268 return cast(item);
269 }
270 }