1 /*
2  * hunt-time: A time library for D programming language.
3  *
4  * Copyright (C) 2015-2018 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.time.util.QueryHelper;
13 
14 import hunt.time.chrono;
15 import hunt.time.Clock;
16 import hunt.time.Exceptions;
17 import hunt.time.DayOfWeek;
18 import hunt.time.Duration;
19 // import hunt.time.format;
20 import hunt.time.Instant;
21 import hunt.time.LocalDate;
22 import hunt.time.LocalDateTime;
23 import hunt.time.LocalTime;
24 import hunt.time.Month;
25 import hunt.time.MonthDay;
26 import hunt.time.OffsetDateTime;
27 import hunt.time.OffsetTime;
28 import hunt.time.Period;
29 import hunt.time.Ser;
30 import hunt.time.temporal;
31 import hunt.time.Year;
32 import hunt.time.YearMonth;
33 // import hunt.time.zone;
34 import hunt.time.ZonedDateTime;
35 import hunt.time.ZoneId;
36 import hunt.time.ZoneOffset;
37 // import hunt.time.ZoneRegion;
38 
39 import hunt.Exceptions;
40 import hunt.logging.ConsoleLogger;
41 
42 import std.stdio;
43 import std.conv;
44 import std.exception;
45 
46 class QueryHelper
47 {
48     static R query(R)(TemporalAccessor t, TemporalQuery!(R) param)
49     {
50         auto typeinfo = typeid(cast(Object) t);
51         warningf("quering: %s", typeinfo.name);
52         implementationMissing(false);
53         // if (typeinfo == typeid(DayOfWeek))
54         // {
55         //     return (cast(DayOfWeek) t).query!R(param);
56         // }
57         // else if (typeinfo == typeid(Parsed))
58         // {
59         //     return (cast(Parsed) t).query!R(param);
60         // }
61         // else if (typeinfo == typeid(Instant))
62         // {
63         //     return (cast(Instant) t).query!R(param);
64         // }
65         // else if (typeinfo == typeid(LocalDate))
66         // {
67         //     return (cast(LocalDate) t).query!R(param);
68         // }
69         // else if (typeinfo == typeid(LocalDateTime))
70         // {
71         //     return (cast(LocalDateTime) t).query!R(param);
72         // }
73         // else if (typeinfo == typeid(LocalTime))
74         // {
75         //     return (cast(LocalTime) t).query!R(param);
76         // }
77         // else if (typeinfo == typeid(Month))
78         // {
79         //     return (cast(Month) t).query!R(param);
80         // }
81         // else if (typeinfo == typeid(MonthDay))
82         // {
83         //     return (cast(MonthDay) t).query!R(param);
84         // }
85         // else if (typeinfo == typeid(OffsetDateTime))
86         // {
87         //     return (cast(OffsetDateTime) t).query!R(param);
88         // }
89         // else if (typeinfo == typeid(OffsetTime))
90         // {
91         //     return (cast(OffsetTime) t).query!R(param);
92         // }
93         // else if (typeinfo == typeid(Year))
94         // {
95         //     return (cast(Year) t).query!R(param);
96         // }
97         // else if (typeinfo == typeid(YearMonth))
98         // {
99         //     return (cast(YearMonth) t).query!R(param);
100         // }
101         // else if (typeinfo == typeid(ZonedDateTime))
102         // {
103         //     return (cast(ZonedDateTime) t).query!R(param);
104         // }
105         // else if (typeinfo == typeid(ZoneOffset))
106         // {
107         //     return (cast(ZoneOffset) t).query!R(param);
108         // }
109         // else if (typeinfo == typeid(AnonymousClass1))
110         // {
111         //     return (cast(AnonymousClass1) t).query!R(param);
112         // }
113         // else if (typeinfo == typeid(AnonymousClass2))
114         // {
115         //     return (cast(AnonymousClass2) t).query!R(param);
116         // }
117         // else if (typeinfo == typeid(AnonymousClass3))
118         // {
119         //     return (cast(AnonymousClass3) t).query!R(param);
120         // }
121         // else if (t !is null)
122         // {
123         //     throw new Exception("unsurpport TemporalAccessor : " ~ typeinfo.name);
124         // }
125         return R.init;
126     }
127 }
128 
129 class AnonymousClass1 : TemporalAccessor
130 {
131     override public bool isSupported(TemporalField field)
132     {
133         return false;
134     }
135 
136     override public long getLong(TemporalField field)
137     {
138         throw new UnsupportedTemporalTypeException("Unsupported field: " ~ field.toString);
139     }
140     /*@SuppressWarnings("unchecked")*/
141     // override
142     public R query(R)(TemporalQuery!(R) query)
143     {
144         if (query == TemporalQueries.chronology())
145         {
146             return cast(R) /* Chronology. */ this;
147         }
148         return  /* TemporalAccessor. */ super_query(query);
149     }
150 
151     R super_query(R)(TemporalQuery!(R) query)
152     {
153         if (query == TemporalQueries.zoneId() || query == TemporalQueries.chronology()
154                 || query == TemporalQueries.precision())
155         {
156             return null;
157         }
158         return query.queryFrom(this);
159     }
160 
161     override ValueRange range(TemporalField field)
162     {
163         if (cast(ChronoField)(field) !is null)
164         {
165             if (isSupported(field))
166             {
167                 return field.range();
168             }
169             throw new UnsupportedTemporalTypeException("Unsupported field: " ~ field.toString);
170         }
171         assert(field, "field");
172         return field.rangeRefinedBy(this);
173     }
174 
175     override int get(TemporalField field)
176     {
177         ValueRange range = range(field);
178         if (range.isIntValue() == false)
179         {
180             throw new UnsupportedTemporalTypeException(
181                     "Invalid field " ~ field.toString ~ " for get() method, use getLong() instead");
182         }
183         long value = getLong(field);
184         if (range.isValidValue(value) == false)
185         {
186             throw new DateTimeException(
187                     "Invalid value for " ~ field.toString ~ " (valid values "
188                     ~ range.toString ~ "): " ~ value.to!string);
189         }
190         return cast(int) value;
191     }
192 
193     override string toString()
194     {
195         return super.toString();
196     }
197 }
198 
199 class AnonymousClass2 : TemporalAccessor
200 {
201     private ChronoLocalDate effectiveDate;
202     private TemporalAccessor temporal;
203     private Chronology effectiveChrono;
204     private ZoneId effectiveZone;
205 
206     this(ChronoLocalDate cld, TemporalAccessor t,Chronology ec,ZoneId ez)
207     {
208         effectiveDate = cld;
209         temporal = t;
210         effectiveChrono = ec;
211         effectiveZone = ez;
212     }
213 
214     override public bool isSupported(TemporalField field)
215     {
216         if (effectiveDate !is null && field.isDateBased())
217         {
218             return effectiveDate.isSupported(field);
219         }
220         return temporal.isSupported(field);
221     }
222 
223     override public ValueRange range(TemporalField field)
224     {
225         if (effectiveDate !is null && field.isDateBased())
226         {
227             return effectiveDate.range(field);
228         }
229         return temporal.range(field);
230     }
231 
232     override public long getLong(TemporalField field)
233     {
234         if (effectiveDate !is null && field.isDateBased())
235         {
236             return effectiveDate.getLong(field);
237         }
238         return temporal.getLong(field);
239     }
240     /*@SuppressWarnings("unchecked")*/
241     /* override */
242     public R query(R)(TemporalQuery!(R) query)
243     {
244         if (query == TemporalQueries.chronology())
245         {
246             return cast(R) effectiveChrono;
247         }
248         if (query == TemporalQueries.zoneId())
249         {
250             return cast(R) effectiveZone;
251         }
252         if (query == TemporalQueries.precision())
253         {
254             return QueryHelper.query!R(temporal, query);
255         }
256         return query.queryFrom(this);
257     }
258 
259     override public string toString()
260     {
261         return temporal.toString ~ (effectiveChrono !is null ? " with chronology " ~ effectiveChrono.toString
262                 : "") ~ (effectiveZone !is null ? " with zone " ~ effectiveZone.toString : "");
263     }
264 
265     override int get(TemporalField field)
266     {
267         ValueRange range = range(field);
268         if (range.isIntValue() == false)
269         {
270             throw new UnsupportedTemporalTypeException(
271                     "Invalid field " ~ field.toString ~ " for get() method, use getLong() instead");
272         }
273         long value = getLong(field);
274         if (range.isValidValue(value) == false)
275         {
276             throw new DateTimeException(
277                     "Invalid value for " ~ field.toString ~ " (valid values "
278                     ~ range.toString ~ "): " ~ value.to!string);
279         }
280         return cast(int) value;
281     }
282 }
283 
284 class AnonymousClass3 : TemporalAccessor
285 {
286     override public bool isSupported(TemporalField field)
287     {
288         return false;
289     }
290 
291     override public long getLong(TemporalField field)
292     {
293         throw new UnsupportedTemporalTypeException("Unsupported field: " ~ typeid(field).name);
294     }
295     /*@SuppressWarnings("unchecked")*/
296     /* override */ public R query(R)(TemporalQuery!(R) query)
297     {
298         if (query == TemporalQueries.zoneId())
299         {
300             return cast(R) /* ZoneId. */ this;
301         }
302         return  /* TemporalAccessor. */ super_query(query);
303     }
304 
305     R super_query(R)(TemporalQuery!(R) query)
306     {
307         if (query == TemporalQueries.zoneId() || query == TemporalQueries.chronology()
308                 || query == TemporalQueries.precision())
309         {
310             return null;
311         }
312         return query.queryFrom(this);
313     }
314 
315     override ValueRange range(TemporalField field)
316     {
317         if (cast(ChronoField)(field) !is null)
318         {
319             if (isSupported(field))
320             {
321                 return field.range();
322             }
323             throw new UnsupportedTemporalTypeException("Unsupported field: " ~ field.toString);
324         }
325         assert(field, "field");
326         return field.rangeRefinedBy(this);
327     }
328 
329     override int get(TemporalField field)
330     {
331         ValueRange range = range(field);
332         if (range.isIntValue() == false)
333         {
334             throw new UnsupportedTemporalTypeException(
335                     "Invalid field " ~ field.toString ~ " for get() method, use getLong() instead");
336         }
337         long value = getLong(field);
338         if (range.isValidValue(value) == false)
339         {
340             throw new DateTimeException(
341                     "Invalid value for " ~ field.toString ~ " (valid values "
342                     ~ range.toString ~ "): " ~ value.to!string);
343         }
344         return cast(int) value;
345     }
346 
347     override string toString()
348     {
349         return super.toString();
350     }
351 }