OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DateTimeTest.java
Go to the documentation of this file.
1 package com.mapd.tests;
2 
3 import org.apache.commons.math3.util.Pair;
4 
5 import java.time.LocalDateTime;
6 import java.time.ZoneOffset;
7 import java.time.format.DateTimeFormatter;
8 import java.time.temporal.ChronoField;
9 import java.time.temporal.ChronoUnit;
10 import java.util.Arrays;
11 import java.util.EnumSet;
12 import java.util.Random;
13 import java.util.function.Function;
14 
15 import ai.heavy.thrift.server.TDBException;
16 import ai.heavy.thrift.server.TTypeInfo;
17 
21 public class DateTimeTest {
22  static enum DateTruncUnit {
23  dtYEAR("YEAR", new Function<LocalDateTime, LocalDateTime>() {
24  @Override
25  public LocalDateTime apply(LocalDateTime t) {
26  t = t.withMonth(1);
27  t = t.withDayOfMonth(1);
28  t = t.truncatedTo(ChronoUnit.DAYS);
29  return t;
30  }
31  }),
32  dtQUARTER("QUARTER", new Function<LocalDateTime, LocalDateTime>() {
33  @Override
34  public LocalDateTime apply(LocalDateTime t) {
35  int month = t.getMonthValue();
36 
37  switch (month) {
38  case 12:
39  case 11:
40  case 10:
41  t = t.withMonth(10);
42  break;
43  case 9:
44  case 8:
45  case 7:
46  t = t.withMonth(7);
47  break;
48  case 6:
49  case 5:
50  case 4:
51  t = t.withMonth(4);
52  break;
53  case 3:
54  case 2:
55  case 1:
56  t = t.withMonth(1);
57  break;
58  };
59 
60  t = t.withDayOfMonth(1);
61  t = t.truncatedTo(ChronoUnit.DAYS);
62  return t;
63  }
64  }),
65  dtMONTH("MONTH", new Function<LocalDateTime, LocalDateTime>() {
66  @Override
67  public LocalDateTime apply(LocalDateTime t) {
68  t = t.withDayOfMonth(1);
69  t = t.truncatedTo(ChronoUnit.DAYS);
70  return t;
71  }
72  }),
73  dtDAY("DAY", new Function<LocalDateTime, LocalDateTime>() {
74  @Override
75  public LocalDateTime apply(LocalDateTime t) {
76  t = t.truncatedTo(ChronoUnit.DAYS);
77  return t;
78  }
79  }),
80  dtHOUR("HOUR", new Function<LocalDateTime, LocalDateTime>() {
81  @Override
82  public LocalDateTime apply(LocalDateTime t) {
83  t = t.truncatedTo(ChronoUnit.HOURS);
84  return t;
85  }
86  }),
87  dtMINUTE("MINUTE", new Function<LocalDateTime, LocalDateTime>() {
88  @Override
89  public LocalDateTime apply(LocalDateTime t) {
90  t = t.truncatedTo(ChronoUnit.MINUTES);
91  return t;
92  }
93  }),
94  dtSECOND("SECOND", new Function<LocalDateTime, LocalDateTime>() {
95  @Override
96  public LocalDateTime apply(LocalDateTime t) {
97  t = t.truncatedTo(ChronoUnit.SECONDS);
98  return t;
99  }
100  }),
101  // dtMILLENNIUM("MILLENNIUM", new Function<LocalDateTime, LocalDateTime>() {
102  // @Override
103  // public LocalDateTime apply(LocalDateTime t) {
104  // int year = t.getYear();
105  // int range = 1000;
106  // int diff = year % range;
107  // if (diff == 0) {
108  // diff = range;
109  // }
110  // year -= diff;
111  // t = t.withYear(year + 1);
112  // t = t.withMonth(1);
113  // t = t.withDayOfMonth(1);
114  // t = t.truncatedTo(ChronoUnit.DAYS);
115  // return t;
116  // }
117  // }),
118  dtCENTURY("CENTURY", new Function<LocalDateTime, LocalDateTime>() {
119  @Override
120  public LocalDateTime apply(LocalDateTime t) {
121  int year = t.getYear();
122  int range = 100;
123  int diff = year % range;
124  if (diff == 0) {
125  diff = range;
126  }
127  year -= diff;
128  t = t.withYear(year + 1);
129 
130  t = t.withMonth(1);
131  t = t.withDayOfMonth(1);
132  t = t.truncatedTo(ChronoUnit.DAYS);
133  return t;
134  }
135  }),
136  dtDECADE("DECADE", new Function<LocalDateTime, LocalDateTime>() {
137  @Override
138  public LocalDateTime apply(LocalDateTime t) {
139  int year = t.getYear();
140  int range = 10;
141  int diff = year % range;
142  year -= diff;
143  t = t.withYear(year);
144  t = t.withMonth(1);
145  t = t.withDayOfMonth(1);
146  t = t.truncatedTo(ChronoUnit.DAYS);
147  return t;
148  }
149  }),
150  dtMILLISECOND("MILLISECOND", new Function<LocalDateTime, LocalDateTime>() {
151  @Override
152  public LocalDateTime apply(LocalDateTime t) {
153  t = t.truncatedTo(ChronoUnit.MILLIS);
154  return t;
155  }
156  }),
157  dtMICROSECOND("MICROSECOND", new Function<LocalDateTime, LocalDateTime>() {
158  @Override
159  public LocalDateTime apply(LocalDateTime t) {
160  t = t.truncatedTo(ChronoUnit.MICROS);
161  return t;
162  }
163  }),
164  dtNANOSECOND("NANOSECOND", new Function<LocalDateTime, LocalDateTime>() {
165  @Override
166  public LocalDateTime apply(LocalDateTime t) {
167  t = t.truncatedTo(ChronoUnit.NANOS);
168  return t;
169  }
170  }),
171  dtWEEK("WEEK", new Function<LocalDateTime, LocalDateTime>() {
172  @Override
173  public LocalDateTime apply(LocalDateTime t) {
174  t = t.with(ChronoField.DAY_OF_WEEK, 1);
175  t = t.truncatedTo(ChronoUnit.DAYS);
176  return t;
177  }
178  }),
179  // dtQUARTERDAY("QUERTERDAY", new Function<LocalDateTime, LocalDateTime>()
180  // {
181  // @Override
182  // public LocalDateTime apply(LocalDateTime t) {
183  // int hour = t.getHour();
184  // hour /= 4;
185  //
186  // t = t.withHour(hour);
187  // t = t.truncatedTo(ChronoUnit.SECONDS);
188  // return t;
189  // }
190  // })
191  ;
192 
193  private String sqlToken;
194  Function<LocalDateTime, LocalDateTime> trunc;
195 
196  private DateTruncUnit(String token, Function<LocalDateTime, LocalDateTime> trunc) {
197  this.sqlToken = token;
198  this.trunc = trunc;
199  }
200  }
201  ;
202 
203  static enum DateExtractUnit {
204  daYEAR("YEAR", new Function<LocalDateTime, Long>() {
205  public Long apply(LocalDateTime t) {
206  return (long) t.get(ChronoField.YEAR);
207  }
208  }),
209  daQUARTER("QUARTER", new Function<LocalDateTime, Long>() {
210  @Override
211  public Long apply(LocalDateTime t) {
212  int month = t.get(ChronoField.MONTH_OF_YEAR);
213  switch (month) {
214  case 1:
215  case 2:
216  case 3:
217  return 1l;
218  case 4:
219  case 5:
220  case 6:
221  return 2l;
222  case 7:
223  case 8:
224  case 9:
225  return 3l;
226  case 10:
227  case 11:
228  case 12:
229  return 4l;
230  }
231  return -1l;
232  }
233  }),
234  daMONTH("MONTH", new Function<LocalDateTime, Long>() {
235  @Override
236  public Long apply(LocalDateTime t) {
237  return (long) t.get(ChronoField.MONTH_OF_YEAR);
238  }
239  }),
240  daDAY("DAY", new Function<LocalDateTime, Long>() {
241  @Override
242  public Long apply(LocalDateTime t) {
243  return (long) t.get(ChronoField.DAY_OF_MONTH);
244  }
245  }),
246  daHOUR("HOUR", new Function<LocalDateTime, Long>() {
247  @Override
248  public Long apply(LocalDateTime t) {
249  return (long) t.get(ChronoField.HOUR_OF_DAY);
250  }
251  }),
252  daMINUTE("MINUTE", new Function<LocalDateTime, Long>() {
253  @Override
254  public Long apply(LocalDateTime t) {
255  return (long) t.get(ChronoField.MINUTE_OF_HOUR);
256  }
257  }),
258  daSECOND("SECOND", new Function<LocalDateTime, Long>() {
259  @Override
260  public Long apply(LocalDateTime t) {
261  return (long) t.get(ChronoField.SECOND_OF_MINUTE);
262  }
263  }),
264  // daMILLENNIUM("MILLENNIUM", ChronoField.YEAR, 1000),
265  // daCENTURY("CENTURY", ChronoField.YEAR, 100),
266  // daDECADE("DECADE", ChronoField.YEAR, 10),
267  daMILLISECOND("MILLISECOND", new Function<LocalDateTime, Long>() {
268  @Override
269  public Long apply(LocalDateTime t) {
270  return t.get(ChronoField.MILLI_OF_SECOND)
271  + (1000L * t.get(ChronoField.SECOND_OF_MINUTE));
272  }
273  }),
274  daMICROSECOND("MICROSECOND", new Function<LocalDateTime, Long>() {
275  @Override
276  public Long apply(LocalDateTime t) {
277  return t.get(ChronoField.MICRO_OF_SECOND)
278  + (1000_000L * t.get(ChronoField.SECOND_OF_MINUTE));
279  }
280  }),
281  daNANOSECOND("NANOSECOND", new Function<LocalDateTime, Long>() {
282  @Override
283  public Long apply(LocalDateTime t) {
284  return t.get(ChronoField.NANO_OF_SECOND)
285  + (1000_000_000L * t.get(ChronoField.SECOND_OF_MINUTE));
286  }
287  }),
288  daWEEK("WEEK", new Function<LocalDateTime, Long>() {
289  @Override
290  public Long apply(LocalDateTime t) {
291  LocalDateTime year = DateTruncUnit.dtYEAR.trunc.apply(t);
292  // bring it to the 4th of Jan (as this is always in the first week of the year)
293  year = year.plusDays(3);
294 
295  // compute the start day of that week (the Monday)
296  LocalDateTime week = DateTruncUnit.dtWEEK.trunc.apply(year);
297 
298  if (week.compareTo(t) > 0) {
299  year = year.minusYears(1);
300  week = DateTruncUnit.dtWEEK.trunc.apply(year);
301  }
302 
303  int weeks = 0;
304  while (week.compareTo(t) <= 0) {
305  weeks++;
306  week = week.plusWeeks(1);
307  }
308 
309  return (long) weeks;
310  }
311  }),
312  // daQUARTERDAY("QUERTERDAY", new Function<LocalDateTime, Integer>() {
313  // @Override
314  // public Integer apply(LocalDateTime t) {
315  // return ((t.get(ChronoField.HOUR_OF_DAY) -1 ) / 4) + 1;
316  // }
317  // }),
318  // daWEEKDAY("WEEKDAYS", new Function<LocalDateTime, Integer>() {
319  // @Override
320  // public Integer apply(LocalDateTime t) {
321  // return t.get(ChronoField.DAY_OF_WEEK);
322  // }
323  // }),
324  daDAYOFYEAR("DOY", new Function<LocalDateTime, Long>() {
325  @Override
326  public Long apply(LocalDateTime t) {
327  return (long) t.get(ChronoField.DAY_OF_YEAR);
328  }
329  });
330 
331  private String sqlToken;
332  private Function<LocalDateTime, Long> extract;
333 
334  private DateExtractUnit(String token, Function<LocalDateTime, Long> f) {
335  this.sqlToken = token;
336  this.extract = f;
337  }
338  }
339  ;
340 
341  static enum DateDiffUnit {
342  daYEAR("YEAR", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
343  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
344  return d.getFirst().until(d.getSecond(), ChronoUnit.YEARS);
345  }
346  }),
347  daQUARTER("QUARTER", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
348  private Long applyCorrect(Pair<LocalDateTime, LocalDateTime> d) {
349  LocalDateTime start = d.getFirst();
350  LocalDateTime end = d.getSecond();
351 
352  int delta = 1;
353  if (start.compareTo(end) > 0) {
354  delta = -1;
355  start = end;
356  end = d.getFirst();
357  }
358 
359  start = DateTruncUnit.dtQUARTER.trunc.apply(start);
360  // end = DateTruncUnit.dtQUARTER.trunc.apply(end);
361  long rc = 0;
362 
363  while (start.compareTo(end) <= 0) {
364  rc += delta;
365  start = start.plusMonths(3);
366  }
367 
368  return rc;
369  }
370 
371  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
372  // this seems to be what mysql does
373  return d.getFirst().until(d.getSecond(), ChronoUnit.MONTHS) / 3;
374  }
375  }),
376  daMONTH("MONTH", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
377  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
378  return d.getFirst().until(d.getSecond(), ChronoUnit.MONTHS);
379  }
380  }),
381  daDAY("DAY", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
382  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
383  return d.getFirst().until(d.getSecond(), ChronoUnit.DAYS);
384  }
385  }),
386  daHOUR("HOUR", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
387  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
388  return d.getFirst().until(d.getSecond(), ChronoUnit.HOURS);
389  }
390  }),
391  daMINUTE("MINUTE", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
392  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
393  return d.getFirst().until(d.getSecond(), ChronoUnit.MINUTES);
394  }
395  }),
396  daSECOND("SECOND", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
397  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
398  return d.getFirst().until(d.getSecond(), ChronoUnit.SECONDS);
399  }
400  }),
401  // daMILLENNIUM("MILLENNIUM", ChronoField.YEAR, 1000),
402  // daCENTURY("CENTURY", ChronoField.YEAR, 100),
403  // daDECADE("DECADE", ChronoField.YEAR, 10),
405  "MILLISECOND", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
406  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
407  return d.getFirst().until(d.getSecond(), ChronoUnit.MILLIS);
408  }
409  }),
411  "MICROSECOND", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
412  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
413  return d.getFirst().until(d.getSecond(), ChronoUnit.MICROS);
414  }
415  }),
416  daNANOSECOND("NANOSECOND", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
417  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
418  return d.getFirst().until(d.getSecond(), ChronoUnit.NANOS);
419  }
420  }),
421  daWEEK("WEEK", new Function<Pair<LocalDateTime, LocalDateTime>, Long>() {
422  public Long apply(Pair<LocalDateTime, LocalDateTime> d) {
423  return d.getFirst().until(d.getSecond(), ChronoUnit.WEEKS);
424  }
425  }),
426  // daQUARTERDAY("QUERTERDAY", new Function<LocalDateTime, Integer>() {
427  // @Override
428  // public Integer apply(LocalDateTime t) {
429  // return ((t.get(ChronoField.HOUR_OF_DAY) -1 ) / 4) + 1;
430  // }
431  // }),
432  // daWEEKDAY("WEEKDAYS", new Function<LocalDateTime, Integer>() {
433  // @Override
434  // public Integer apply(LocalDateTime t) {
435  // return t.get(ChronoField.DAY_OF_WEEK);
436  // }
437  // }),
438  ;
439 
440  private String sqlToken;
441  private Function<Pair<LocalDateTime, LocalDateTime>, Long> diff;
442 
443  private DateDiffUnit(
444  String token, Function<Pair<LocalDateTime, LocalDateTime>, Long> diff) {
445  this.sqlToken = token;
446  this.diff = diff;
447  }
448  }
449  ;
450 
451  static enum DateAddUnit {
452  daYEAR("YEAR", 99, new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
453  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
454  return t.getFirst().plus(t.getSecond(), ChronoUnit.YEARS);
455  }
456  }),
458  "QUARTER", 10 * 3, new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
459  @Override
460  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
461  return t.getFirst().plus(t.getSecond() * 3, ChronoUnit.MONTHS);
462  }
463  }),
464  daMONTH("MONTH", 99, new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
465  @Override
466  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
467  return t.getFirst().plus(t.getSecond(), ChronoUnit.MONTHS);
468  }
469  }),
470  daDAY("DAY", 99, new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
471  @Override
472  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
473  return t.getFirst().plus(t.getSecond(), ChronoUnit.DAYS);
474  }
475  }),
476  daHOUR("HOUR", 99, new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
477  @Override
478  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
479  return t.getFirst().plus(t.getSecond(), ChronoUnit.HOURS);
480  }
481  }),
482  daMINUTE("MINUTE", 99, new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
483  @Override
484  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
485  return t.getFirst().plus(t.getSecond(), ChronoUnit.MINUTES);
486  }
487  }),
488  daSECOND("SECOND", 99, new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
489  @Override
490  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
491  return t.getFirst().plus(t.getSecond(), ChronoUnit.SECONDS);
492  }
493  }),
494  // daMILLENNIUM("MILLENNIUM", ChronoField.YEAR, 1000),
495  // daCENTURY("CENTURY", ChronoField.YEAR, 100),
496  // daDECADE("DECADE", ChronoField.YEAR, 10),
497  daMILLISECOND("MILLISECOND",
498  12 * 30 * 24 * 60 * 60 * 1000L,
499  new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
500  @Override
501  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
502  return t.getFirst().plus(t.getSecond(), ChronoUnit.MILLIS);
503  }
504  }),
505  daMICROSECOND("MICROSECOND",
506  12 * 30 * 24 * 60 * 60 * 1000 * 1000,
507  new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
508  @Override
509  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
510  return t.getFirst().plus(t.getSecond(), ChronoUnit.MICROS);
511  }
512  }),
513  daNANOSECOND("NANOSECOND",
514  12 * 30 * 24 * 60 * 60 * 1000 * 1000 * 1000,
515  new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
516  @Override
517  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
518  return t.getFirst().plus(t.getSecond(), ChronoUnit.NANOS);
519  }
520  }),
521  daWEEK("WEEK", 53, new Function<Pair<LocalDateTime, Long>, LocalDateTime>() {
522  @Override
523  public LocalDateTime apply(Pair<LocalDateTime, Long> t) {
524  return t.getFirst().plus(t.getSecond(), ChronoUnit.WEEKS);
525  }
526  }),
527  // daQUARTERDAY("QUERTERDAY", new Function<LocalDateTime, Integer>() {
528  // @Override
529  // public Integer apply(LocalDateTime t) {
530  // return ((t.get(ChronoField.HOUR_OF_DAY) -1 ) / 4) + 1;
531  // }
532  // }),
533  // daWEEKDAY("WEEKDAYS", new Function<LocalDateTime, Integer>() {
534  // @Override
535  // public Integer apply(LocalDateTime t) {
536  // return t.get(ChronoField.DAY_OF_WEEK);
537  // }
538  // }),
539  ;
540 
541  private String sqlToken;
542  private Function<Pair<LocalDateTime, Long>, LocalDateTime> add;
543  private long max;
544 
545  private DateAddUnit(String token,
546  long max,
547  Function<Pair<LocalDateTime, Long>, LocalDateTime> f) {
548  this.sqlToken = token;
549  this.max = max;
550  this.add = f;
551  }
552  }
553  ;
554 
555  static LocalDateTime createRandomDateTime(Random r) {
556  try {
557  int year = 1900 + r.nextInt(200);
558  int month = 1 + r.nextInt(12);
559  int dayOfMonth = 1 + r.nextInt(31);
560  int hour = r.nextInt(24);
561  int minute = r.nextInt(60);
562  int second = r.nextInt(60);
563  int nanoOfSecond = r.nextInt(1000 * 1000 * 1000);
564 
565  return LocalDateTime.of(
566  year, month, dayOfMonth, hour, minute, second, nanoOfSecond);
567  } catch (Exception e) {
568  return createRandomDateTime(r);
569  }
570  }
571 
572  static enum Encoding {
573  TIMESTAMP("TIMESTAMP",
574  "'TIMESTAMP' ''yyyy-MM-dd HH:mm:ss''",
575  ChronoUnit.SECONDS,
576  LocalDateTime.ofEpochSecond(-30610224000L, 0, ZoneOffset.UTC),
577  LocalDateTime.ofEpochSecond(29379542399L, 0, ZoneOffset.UTC)),
578  TIMESTAMP_0("TIMESTAMP(0)",
579  "'TIMESTAMP(0)' ''yyyy-MM-dd HH:mm:ss''",
580  ChronoUnit.SECONDS,
581  LocalDateTime.ofEpochSecond(-30610224000L, 0, ZoneOffset.UTC),
582  LocalDateTime.ofEpochSecond(29379542399L, 0, ZoneOffset.UTC)),
583  TIMESTAMP_3("TIMESTAMP(3)",
584  "'TIMESTAMP(3)' ''yyyy-MM-dd HH:mm:ss.SSS''",
585  ChronoUnit.MILLIS,
586  LocalDateTime.ofEpochSecond(-30610224000L, 0, ZoneOffset.UTC),
587  LocalDateTime.ofEpochSecond(29379542399L, 0, ZoneOffset.UTC)),
588  TIMESTAMP_6("TIMESTAMP(6)",
589  "'TIMESTAMP(6)' ''yyyy-MM-dd HH:mm:ss.SSSSSS''",
590  ChronoUnit.MICROS,
591  LocalDateTime.ofEpochSecond(-30610224000L, 0, ZoneOffset.UTC),
592  LocalDateTime.ofEpochSecond(29379542399L, 0, ZoneOffset.UTC)),
593  TIMESTAMP_9("TIMESTAMP(9)",
594  "'TIMESTAMP(9)' ''yyyy-MM-dd HH:mm:ss.SSSSSSSSS''",
595  ChronoUnit.NANOS,
596  LocalDateTime.ofEpochSecond(-9223372036L, 0, ZoneOffset.UTC),
597  LocalDateTime.ofEpochSecond(9223372036L, 0, ZoneOffset.UTC)),
598  TIMESTAMP_FIXED_32("TIMESTAMP ENCODING FIXED(32)",
599  "'TIMESTAMP' ''yyyy-MM-dd HH:mm:ss''",
600  ChronoUnit.SECONDS,
601  LocalDateTime.ofEpochSecond(Integer.MIN_VALUE + 1, 0, ZoneOffset.UTC),
602  LocalDateTime.ofEpochSecond(Integer.MAX_VALUE, 0, ZoneOffset.UTC)),
603  DATE("DATE",
604  "'DATE' ''yyyy-MM-dd''",
605  ChronoUnit.DAYS,
606  LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.UTC).plusDays(-2147483648L),
607  LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.UTC).plusDays(2147483647L)),
608  DATE_DAYS_16("DATE ENCODING DAYS(16)",
609  "'DATE' ''yyyy-MM-dd''",
610  ChronoUnit.DAYS,
611  LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.UTC)
612  .plusDays(Short.MIN_VALUE + 1),
613  LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.UTC).plusDays(Short.MAX_VALUE)),
614  DATE_DAYS_32("DATE ENCODING DAYS(32)",
615  "'DATE' ''yyyy-MM-dd''",
616  ChronoUnit.DAYS,
617  LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.UTC).plusDays(-2147483648L),
618  LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.UTC).plusDays(2147483647L));
619 
620  DateTimeFormatter formatter;
621  String sqlType;
622  ChronoUnit toClear;
623  LocalDateTime min;
624  LocalDateTime max;
625 
626  Encoding(String sqlType,
627  String pattern,
628  ChronoUnit unit,
629  LocalDateTime min,
630  LocalDateTime max) {
631  this.sqlType = sqlType;
632  formatter = DateTimeFormatter.ofPattern(pattern);
633  this.toClear = unit;
634  this.min = min;
635  this.max = max;
636  }
637 
638  public String toSqlColumn(String prefx, LocalDateTime val) {
639  if (null != val) return prefx + "_" + name() + " /* " + toSql(val) + " */";
640  return prefx + "_" + name();
641  }
642 
643  public String toSql(LocalDateTime d) {
644  return formatter.format(d);
645  }
646 
647  public LocalDateTime clear(LocalDateTime d) {
648  if (null != toClear) {
649  d = d.truncatedTo(toClear);
650  }
651 
652  return d;
653  }
654 
655  public LocalDateTime clearForDateAddResult(LocalDateTime d) {
656  if (null != toClear) {
657  if (toClear == ChronoUnit.DAYS) {
658  d = d.truncatedTo(ChronoUnit.SECONDS);
659  } else {
660  d = d.truncatedTo(toClear);
661  }
662  }
663 
664  return d;
665  }
666 
667  public boolean isValid(LocalDateTime t) {
668  return t.isAfter(min) && t.isBefore(max);
669  }
670  }
671 
672  static LocalDateTime getDateTimeFromQuery(HeavyDBTestClient client, String sql)
673  throws Exception {
674  try {
675  ai.heavy.thrift.server.TQueryResult res = client.runSql(sql);
676  LocalDateTime r = null;
677  if (res.row_set.is_columnar) {
678  TTypeInfo tt = res.row_set.row_desc.get(0).col_type;
679  int pow = (int) Math.pow(10, tt.precision);
680  long val = res.row_set.columns.get(0).data.int_col.get(0);
681  int nanosPow = (int) Math.pow(10, 9 - tt.precision);
682  long nanos = (val % pow);
683  if (nanos < 0) {
684  nanos = pow + nanos;
685  }
686  nanos *= nanosPow;
687  r = LocalDateTime.ofEpochSecond(
688  Math.floorDiv(val, pow), (int) nanos, ZoneOffset.UTC);
689 
690  } else {
691  throw new RuntimeException("Unsupported!");
692  }
693 
694  return r;
695  } catch (TDBException e) {
696  System.out.println("Query failed: " + sql + " -- " + e.getError_msg());
697  return LocalDateTime.MIN;
698 
699  } catch (Exception e) {
700  System.out.println("Query failed: " + sql + " -- " + e.getMessage());
701  return LocalDateTime.MIN;
702  }
703  }
704 
705  static long getLongFromQuery(HeavyDBTestClient client, String sql) throws Exception {
706  try {
707  ai.heavy.thrift.server.TQueryResult res = client.runSql(sql);
708  long r = -1;
709  if (res.row_set.is_columnar) {
710  long val = res.row_set.columns.get(0).data.int_col.get(0);
711  r = val;
712  } else {
713  throw new RuntimeException("Unsupported!");
714  }
715  return r;
716  } catch (TDBException e) {
717  System.out.println("Query failed: " + sql + " -- " + e.getError_msg());
718  return Long.MIN_VALUE;
719  } catch (Exception e) {
720  System.out.println("Query failed: " + sql + " -- " + e.getMessage());
721  return Long.MIN_VALUE;
722  }
723  }
724 
725  public static LocalDateTime testDateTrunc(
726  LocalDateTime d, DateTruncUnit f, HeavyDBTestClient client, Encoding enc)
727  throws Exception {
728  if (!enc.isValid(d)) {
729  return d;
730  }
731 
732  String sql = "SELECT DATE_TRUNC('" + f.sqlToken + "', " + enc.toSql(d) + ");";
733  LocalDateTime r = getDateTimeFromQuery(client, sql);
734  LocalDateTime expected = f.trunc.apply(d);
735  expected = enc.clear(expected);
736 
737  Fuzzy rc = Fuzzy.compare(expected, r, enc);
738  if (resultsToDump.contains(rc)) {
739  System.out.println("Query " + rc + ": " + sql
740  + " -> expected: " + expected.toString() + " got " + r.toString());
741  }
742 
743  return testDateTruncTable(d, f, client, enc);
744  }
745 
746  private static void updateValues(
747  HeavyDBTestClient client, LocalDateTime a, Encoding aEnc) throws Exception {
748  updateValues(client, a, aEnc, null, null);
749  }
750 
751  private static void updateValues(HeavyDBTestClient client,
752  LocalDateTime a,
753  Encoding aEnc,
754  LocalDateTime b,
755  Encoding bEnc) throws Exception {
756  String sqlUpdate = "UPDATE DateTimeTest set " + aEnc.toSqlColumn("a", null) + " = "
757  + aEnc.toSql(a);
758 
759  if (null != b) {
760  sqlUpdate += ", " + bEnc.toSqlColumn("b", null) + " = " + bEnc.toSql(b);
761  }
762 
763  sqlUpdate += ";";
764 
765  try {
766  client.runSql(sqlUpdate);
767  } catch (TDBException e) {
768  System.out.println("Update failed: " + sqlUpdate + " " + e.getError_msg());
769  }
770  }
771 
772  public static LocalDateTime testDateTruncTable(
773  LocalDateTime d, DateTruncUnit f, HeavyDBTestClient client, Encoding enc)
774  throws Exception {
775  updateValues(client, d, enc);
776  String sql = "SELECT DATE_TRUNC('" + f.sqlToken + "', " + enc.toSqlColumn("a", d)
777  + ") FROM DateTimeTest;";
778  LocalDateTime r = getDateTimeFromQuery(client, sql);
779  LocalDateTime expected = f.trunc.apply(d);
780  expected = enc.clear(expected);
781 
782  Fuzzy rc = Fuzzy.compare(expected, r, enc);
783  if (resultsToDump.contains(rc)) {
784  System.out.println("Query " + rc + ": " + sql
785  + " -> expected: " + expected.toString() + " got " + r.toString());
786  }
787 
788  return expected;
789  }
790 
791  public static void testDateExtract(
792  LocalDateTime d, DateExtractUnit f, HeavyDBTestClient client, Encoding enc)
793  throws Exception {
794  String sql = "SELECT EXTRACT(" + f.sqlToken + " FROM " + enc.toSql(d) + ");";
795  long r = getLongFromQuery(client, sql);
796 
797  d = enc.clear(d);
798  long expected = f.extract.apply(d);
799 
800  Fuzzy rc = Fuzzy.compare(expected, r);
801  if (resultsToDump.contains(rc)) {
802  System.out.println(
803  "Query " + rc + ": " + sql + " -> expected: " + expected + " got " + r);
804  }
805 
806  testDateExtractTable(d, f, client, enc);
807  }
808 
809  public static void testDateExtractTable(
810  LocalDateTime d, DateExtractUnit f, HeavyDBTestClient client, Encoding enc)
811  throws Exception {
812  if (!enc.isValid(d)) {
813  return;
814  }
815 
816  updateValues(client, d, enc);
817  String sql = "SELECT EXTRACT(" + f.sqlToken + " FROM " + enc.toSqlColumn("a", d)
818  + ") FROM DateTimeTest;";
819  long r = getLongFromQuery(client, sql);
820 
821  d = enc.clear(d);
822  long expected = f.extract.apply(d);
823 
824  Fuzzy rc = Fuzzy.compare(expected, r);
825  if (resultsToDump.contains(rc)) {
826  System.out.println(
827  "Query " + rc + ": " + sql + " -> expected: " + expected + " got " + r);
828  }
829  }
830 
831  public static void testDiff(String fn,
832  LocalDateTime d0,
833  LocalDateTime d1,
834  DateDiffUnit f,
835  HeavyDBTestClient client,
836  Encoding enc0,
837  Encoding enc1) throws Exception {
838  String sql = "SELECT " + fn + "(" + f.sqlToken + ", " + enc0.toSql(d0) + ", "
839  + enc1.toSql(d1) + ");";
840  long r = getLongFromQuery(client, sql);
841  d0 = enc0.clear(d0);
842  d1 = enc1.clear(d1);
843 
844  long expected = f.diff.apply(Pair.create(d0, d1));
845 
846  Fuzzy rc = Fuzzy.compare(expected, r);
847  if (resultsToDump.contains(rc)) {
848  System.out.println(
849  "Query " + rc + ": " + sql + " -> expected: " + expected + " got " + r);
850  }
851 
852  testDiffTable(fn, d0, d1, f, client, enc0, enc1);
853  }
854 
855  public static void testDiffTable(String fn,
856  LocalDateTime d0,
857  LocalDateTime d1,
858  DateDiffUnit f,
859  HeavyDBTestClient client,
860  Encoding enc0,
861  Encoding enc1) throws Exception {
862  if (!enc0.isValid(d0) || !enc1.isValid(d1)) {
863  return;
864  }
865 
866  updateValues(client, d0, enc0, d1, enc1);
867  String sql = "SELECT " + fn + "(" + f.sqlToken + ", " + enc0.toSqlColumn("a", d0)
868  + ", " + enc1.toSqlColumn("b", d1) + ") FROM DateTimeTest;";
869  long r = getLongFromQuery(client, sql);
870  d0 = enc0.clear(d0);
871  d1 = enc1.clear(d1);
872 
873  long expected = f.diff.apply(Pair.create(d0, d1));
874 
875  Fuzzy rc = Fuzzy.compare(expected, r);
876  if (resultsToDump.contains(rc)) {
877  System.out.println(
878  "Query " + rc + ": " + sql + " -> expected: " + expected + " got " + r);
879  }
880  }
881 
882  public static void testDateAdd(String fn,
883  LocalDateTime d,
884  DateAddUnit f,
885  long units,
886  HeavyDBTestClient client,
887  Encoding enc) throws Exception {
888  String sql =
889  "SELECT " + fn + "(" + f.sqlToken + ", " + units + ", " + enc.toSql(d) + ");";
890  LocalDateTime r = getDateTimeFromQuery(client, sql);
891 
892  LocalDateTime expected = f.add.apply(Pair.create(enc.clear(d), units));
893  expected = enc.clearForDateAddResult(expected);
894 
895  Fuzzy rc = Fuzzy.compareDateAdd(expected, r, enc);
896  if (resultsToDump.contains(rc)) {
897  System.out.println("Query " + rc + ": " + sql
898  + " -> expected: " + expected.toString() + " got " + r.toString());
899  }
900 
901  testDateAddTable(fn, d, f, units, client, enc);
902  }
903 
904  public static void testDateAddTable(String fn,
905  LocalDateTime d,
906  DateAddUnit f,
907  long units,
908  HeavyDBTestClient client,
909  Encoding enc) throws Exception {
910  if (!enc.isValid(d)) {
911  return;
912  }
913 
914  updateValues(client, d, enc);
915  String sql = "SELECT " + fn + "(" + f.sqlToken + ", " + units + ", "
916  + enc.toSqlColumn("a", d) + ") FROM DateTimeTest;";
917  LocalDateTime r = getDateTimeFromQuery(client, sql);
918 
919  LocalDateTime expected = f.add.apply(Pair.create(enc.clear(d), units));
920  expected = enc.clearForDateAddResult(expected);
921 
922  Fuzzy rc = Fuzzy.compareDateAdd(expected, r, enc);
923  if (resultsToDump.contains(rc)) {
924  System.out.println("Query " + rc + ": " + sql
925  + " -> expected: " + expected.toString() + " got " + r.toString());
926  }
927  }
928 
929  static EnumSet resultsToDump = EnumSet.of(Fuzzy.failed, Fuzzy.okish);
930 
931  static EnumSet addAllowed = EnumSet.allOf(DateAddUnit.class);
932 
933  static {
934  addAllowed.remove(DateAddUnit.daQUARTER);
935  addAllowed.remove(DateAddUnit.daMILLISECOND);
936  addAllowed.remove(DateAddUnit.daMICROSECOND);
937  addAllowed.remove(DateAddUnit.daNANOSECOND);
938  addAllowed.remove(DateAddUnit.daWEEK);
939  }
940 
941  public static void testAdd(LocalDateTime d,
942  DateAddUnit f,
943  long units,
944  HeavyDBTestClient client,
945  Encoding enc) throws Exception {
946  if (!addAllowed.contains(f)) {
947  return;
948  }
949 
950  String sql =
951  "SELECT " + enc.toSql(d) + " + INTERVAL '" + units + "' " + f.sqlToken + " ;";
952  LocalDateTime r = getDateTimeFromQuery(client, sql);
953 
954  LocalDateTime expected = f.add.apply(Pair.create(enc.clear(d), units));
955  expected = enc.clearForDateAddResult(expected);
956 
957  Fuzzy rc = Fuzzy.compareDateAdd(expected, r, enc);
958  if (resultsToDump.contains(rc)) {
959  System.out.println("Query " + rc + ": " + sql
960  + " -> expected: " + expected.toString() + " got " + r.toString());
961  }
962  }
963 
964  public static void testSub(LocalDateTime d,
965  DateAddUnit f,
966  long units,
967  HeavyDBTestClient client,
968  Encoding enc) throws Exception {
969  if (!addAllowed.contains(f)) {
970  return;
971  }
972 
973  long toSub = -units;
974 
975  String sql =
976  "SELECT " + enc.toSql(d) + " - INTERVAL '" + toSub + "' " + f.sqlToken + " ;";
977  LocalDateTime r = getDateTimeFromQuery(client, sql);
978 
979  LocalDateTime expected = f.add.apply(Pair.create(enc.clear(d), units));
980  expected = enc.clearForDateAddResult(expected);
981 
982  Fuzzy rc = Fuzzy.compareDateAdd(expected, r, enc);
983  if (resultsToDump.contains(rc)) {
984  System.out.println("Query " + rc + ": " + sql
985  + " -> expected: " + expected.toString() + " got " + r.toString());
986  }
987  }
988 
989  static enum Fuzzy {
990  ok,
993 
994  static Fuzzy compare(LocalDateTime expected, LocalDateTime result, Encoding enc) {
995  if (expected.equals(result)) return ok;
996 
997  LocalDateTime okish = result.minus(1, ChronoUnit.NANOS);
998  okish = enc.clear(okish);
999 
1000  if (expected.equals(okish)) return Fuzzy.okish;
1001 
1002  okish = result.plus(1, ChronoUnit.NANOS);
1003  okish = enc.clear(okish);
1004 
1005  if (expected.equals(okish)) return Fuzzy.okish;
1006 
1007  return failed;
1008  }
1009 
1010  static Fuzzy compare(long expected, long result) {
1011  if (expected == result) return ok;
1012 
1013  long okish = result - 1;
1014 
1015  if (expected == okish) return Fuzzy.okish;
1016 
1017  okish = result + 1;
1018 
1019  if (expected == okish) return Fuzzy.okish;
1020 
1021  if ((result == 59 && expected == 0) || (result == 0 && expected == 59)) {
1022  // for minutes and seconds
1023  return Fuzzy.okish;
1024  }
1025 
1026  if ((result == 23 && expected == 0) || (result == 0 && expected == 23)) {
1027  // for hours
1028  return Fuzzy.okish;
1029  }
1030 
1031  return failed;
1032  }
1033 
1035  LocalDateTime expected, LocalDateTime result, Encoding enc) {
1036  if (expected.equals(result)) return ok;
1037 
1038  LocalDateTime okish = result.minus(1, ChronoUnit.NANOS);
1039  okish = enc.clearForDateAddResult(okish);
1040 
1041  if (expected.equals(okish)) return Fuzzy.okish;
1042 
1043  okish = result.plus(1, ChronoUnit.NANOS);
1044  okish = enc.clearForDateAddResult(okish);
1045 
1046  if (expected.equals(okish)) return Fuzzy.okish;
1047 
1048  return failed;
1049  }
1050  }
1051 
1052  public static void createTestTable(HeavyDBTestClient client) throws Exception {
1053  client.runSql("DROP TABLE IF EXISTS DateTimeTest;");
1054  String sqlCreate = "CREATE TABLE DateTimeTest(id int";
1055  String sqlInsert = "INSERT INTO DateTimeTest VALUES(0";
1056  for (Encoding e : Encoding.values()) {
1057  sqlCreate += ", " + e.toSqlColumn("a", null) + " " + e.sqlType;
1058  sqlCreate += ", " + e.toSqlColumn("b", null) + " " + e.sqlType;
1059  sqlInsert += ", null, null";
1060  }
1061 
1062  sqlCreate += ");";
1063  sqlInsert += ");";
1064 
1065  client.runSql(sqlCreate);
1066  client.runSql(sqlInsert);
1067 
1068  System.out.println("CREATE: " + sqlCreate);
1069  System.out.println("INSERT: " + sqlInsert);
1070  }
1071 
1072  public static void main(String[] args) throws Exception {
1073  long seed;
1074 
1075  // to reproduce a previous run, use the same seed
1076  if (0 < args.length) {
1077  seed = Long.parseLong(args[0], 10);
1078  } else {
1079  seed = System.currentTimeMillis();
1080  }
1081 
1082  System.out.println("Seed: " + seed);
1083  Random r = new Random(seed);
1084 
1085  HeavyDBTestClient su = HeavyDBTestClient.getClient(
1086  "localhost", 6274, "heavyai", "admin", "HyperInteractive");
1087  LocalDateTime d0 = createRandomDateTime(r);
1088  LocalDateTime d1 = createRandomDateTime(r);
1089 
1090  createTestTable(su);
1091 
1092  // don't dump OK results
1093  resultsToDump = EnumSet.of(Fuzzy.failed, Fuzzy.okish);
1094  boolean testTrunc = true;
1095  boolean testExtract = true;
1096  boolean testDiff = true;
1097  boolean testAdd = true;
1098 
1099  if (testTrunc) {
1100  for (Encoding enc0 : Encoding.values()) {
1101  for (DateTruncUnit f : DateTruncUnit.values()) {
1102  LocalDateTime e = testDateTrunc(d0, f, su, enc0);
1103  e = e.minus(1, ChronoUnit.NANOS);
1104  testDateTrunc(e, f, su, enc0);
1105  e = testDateTrunc(d1, f, su, enc0);
1106  e = e.minus(1, ChronoUnit.NANOS);
1107  testDateTrunc(e, f, su, enc0);
1108  }
1109  }
1110  }
1111 
1112  if (testExtract) {
1113  for (Encoding enc0 : Encoding.values()) {
1114  for (DateExtractUnit f : DateExtractUnit.values()) {
1115  testDateExtract(d0, f, su, enc0);
1116  testDateExtract(d0.minusNanos(1), f, su, enc0);
1117  testDateExtract(d0.plusNanos(1), f, su, enc0);
1118  testDateExtract(d1, f, su, enc0);
1119  testDateExtract(d1.minusNanos(1), f, su, enc0);
1120  testDateExtract(d1.plusNanos(1), f, su, enc0);
1121  }
1122  }
1123  }
1124 
1125  if (testDiff) {
1126  for (Encoding enc0 : Encoding.values()) {
1127  for (Encoding enc1 : Encoding.values()) {
1128  for (DateDiffUnit f : DateDiffUnit.values()) {
1129  for (String fn : Arrays.asList("TIMESTAMPDIFF" /* , "DATEDIFF" */)) {
1130  testDiff(fn, d0, d1, f, su, enc0, enc1);
1131  testDiff(fn, d1, d0, f, su, enc0, enc1);
1132  testDiff(fn, d0, d0, f, su, enc0, enc1);
1133  testDiff(fn, d1, d1, f, su, enc0, enc1);
1134  }
1135  }
1136  }
1137  }
1138  }
1139 
1140  if (testAdd) {
1141  for (DateAddUnit f : DateAddUnit.values()) {
1142  long units = r.nextLong() % f.max;
1143  if (r.nextBoolean()) {
1144  units *= -1L;
1145  }
1146  for (Encoding enc0 : Encoding.values()) {
1147  for (String fn : Arrays.asList("TIMESTAMPADD", "DATEADD")) {
1148  testDateAdd(fn, d0, f, units, su, enc0);
1149  testDateAdd(fn, d1, f, units, su, enc0);
1150  }
1151  testAdd(d0, f, units, su, enc0);
1152  testSub(d0, f, units, su, enc0);
1153  testAdd(d1, f, units, su, enc0);
1154  testSub(d1, f, units, su, enc0);
1155  }
1156  }
1157  }
1158  }
1159 }
static LocalDateTime createRandomDateTime(Random r)
DateTruncUnit(String token, Function< LocalDateTime, LocalDateTime > trunc)
static void testDateAdd(String fn, LocalDateTime d, DateAddUnit f, long units, HeavyDBTestClient client, Encoding enc)
String toSqlColumn(String prefx, LocalDateTime val)
DateAddUnit(String token, long max, Function< Pair< LocalDateTime, Long >, LocalDateTime > f)
static LocalDateTime getDateTimeFromQuery(HeavyDBTestClient client, String sql)
static Fuzzy compare(LocalDateTime expected, LocalDateTime result, Encoding enc)
static void testDiff(String fn, LocalDateTime d0, LocalDateTime d1, DateDiffUnit f, HeavyDBTestClient client, Encoding enc0, Encoding enc1)
static LocalDateTime testDateTruncTable(LocalDateTime d, DateTruncUnit f, HeavyDBTestClient client, Encoding enc)
static void createTestTable(HeavyDBTestClient client)
static void testDateExtract(LocalDateTime d, DateExtractUnit f, HeavyDBTestClient client, Encoding enc)
static Fuzzy compare(long expected, long result)
static Fuzzy compareDateAdd(LocalDateTime expected, LocalDateTime result, Encoding enc)
Definition: DateAdd.h:47
static void updateValues(HeavyDBTestClient client, LocalDateTime a, Encoding aEnc, LocalDateTime b, Encoding bEnc)
Function< LocalDateTime, LocalDateTime > trunc
constexpr double a
Definition: Utm.h:32
DateExtractUnit(String token, Function< LocalDateTime, Long > f)
static void updateValues(HeavyDBTestClient client, LocalDateTime a, Encoding aEnc)
Definition: DateAdd.h:43
Function< Pair< LocalDateTime, LocalDateTime >, Long > diff
Encoding(String sqlType, String pattern, ChronoUnit unit, LocalDateTime min, LocalDateTime max)
Definition: DateAdd.h:56
static void testDateAddTable(String fn, LocalDateTime d, DateAddUnit f, long units, HeavyDBTestClient client, Encoding enc)
static void main(String[] args)
DateDiffUnit(String token, Function< Pair< LocalDateTime, LocalDateTime >, Long > diff)
Function< Pair< LocalDateTime, Long >, LocalDateTime > add
Function< LocalDateTime, Long > extract
torch::Tensor f(torch::Tensor x, torch::Tensor W_target, torch::Tensor b_target)
static long getLongFromQuery(HeavyDBTestClient client, String sql)
static void testSub(LocalDateTime d, DateAddUnit f, long units, HeavyDBTestClient client, Encoding enc)
LocalDateTime clearForDateAddResult(LocalDateTime d)
static void testDiffTable(String fn, LocalDateTime d0, LocalDateTime d1, DateDiffUnit f, HeavyDBTestClient client, Encoding enc0, Encoding enc1)
Definition: DateAdd.h:46
string name
Definition: setup.in.py:72
static void testAdd(LocalDateTime d, DateAddUnit f, long units, HeavyDBTestClient client, Encoding enc)
static LocalDateTime testDateTrunc(LocalDateTime d, DateTruncUnit f, HeavyDBTestClient client, Encoding enc)
LocalDateTime clear(LocalDateTime d)
static void testDateExtractTable(LocalDateTime d, DateExtractUnit f, HeavyDBTestClient client, Encoding enc)
boolean isValid(LocalDateTime t)