DBInstant.java

  1. /*
  2.  * Copyright 2013 Gregory Graham.
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *      http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. package nz.co.gregs.dbvolution.datatypes;

  17. import java.sql.ResultSet;
  18. import java.sql.SQLException;
  19. import java.sql.Timestamp;
  20. import java.text.ParseException;
  21. import java.time.Instant;
  22. import java.time.LocalDate;
  23. import java.time.LocalDateTime;
  24. import java.time.ZoneId;
  25. import java.time.ZoneOffset;
  26. import java.time.ZonedDateTime;
  27. import java.time.format.DateTimeFormatter;
  28. import java.util.*;
  29. import java.util.stream.Collectors;
  30. import nz.co.gregs.dbvolution.DBReport;
  31. import nz.co.gregs.dbvolution.DBRow;
  32. import nz.co.gregs.dbvolution.columns.InstantColumn;
  33. import nz.co.gregs.dbvolution.databases.SQLiteDB;
  34. import nz.co.gregs.dbvolution.databases.definitions.DBDefinition;
  35. import nz.co.gregs.dbvolution.exceptions.DBRuntimeException;
  36. import nz.co.gregs.dbvolution.exceptions.IncorrectRowProviderInstanceSuppliedException;
  37. import nz.co.gregs.dbvolution.expressions.InstantExpression;
  38. import nz.co.gregs.dbvolution.expressions.StringExpression;
  39. import nz.co.gregs.dbvolution.operators.DBGreaterThanOperator;
  40. import nz.co.gregs.dbvolution.operators.DBGreaterThanOrEqualsOperator;
  41. import nz.co.gregs.dbvolution.operators.DBLessThanOperator;
  42. import nz.co.gregs.dbvolution.operators.DBLessThanOrEqualOperator;
  43. import nz.co.gregs.dbvolution.operators.DBPermittedRangeExclusiveOperator;
  44. import nz.co.gregs.dbvolution.operators.DBPermittedRangeInclusiveOperator;
  45. import nz.co.gregs.dbvolution.operators.DBPermittedRangeOperator;
  46. import nz.co.gregs.dbvolution.operators.DBPermittedValuesOperator;
  47. import nz.co.gregs.dbvolution.query.RowDefinition;
  48. import nz.co.gregs.dbvolution.results.InstantResult;
  49. import nz.co.gregs.dbvolution.utility.comparators.ComparableComparator;

  50. /**
  51.  * Encapsulates database values that are Dates.
  52.  *
  53.  * <p>
  54.  * Use DBDate when the column is a date datatype, even in databases where the
  55.  * native date type is a String (i.e. {@link SQLiteDB}).
  56.  *
  57.  * <p>
  58.  * Generally DBDate is declared inside your DBRow sub-class as:
  59.  * {@code @DBColumn public DBDate myBoolColumn = new DBDate();}
  60.  *
  61.  * <p style="color: #F90;">Support DBvolution at
  62.  * <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
  63.  *
  64.  * @author Gregory Graham
  65.  */
  66. public class DBInstant extends QueryableDatatype<Instant> implements InstantResult {

  67.     private static final long serialVersionUID = 1L;
  68. //  private final SimpleDateFormat toStringFormat = new SimpleDateFormat("yyyy-MM-dd KK:mm:ss.SSSa ZZZZ");
  69. //  private final DateTimeFormatter toStringFormat = DateTimeFormatter.ofPattern("uuuu-MM-dd kk:mm:ss.SSS ZZZZ");

  70.     /**
  71.      * The default constructor for DBDate.
  72.      *
  73.      * <p>
  74.      * Creates an unset undefined DBDate object.
  75.      *
  76.      */
  77.     public DBInstant() {
  78.         super();
  79.     }

  80.     /**
  81.      * Creates a DBDate with the value provided.
  82.      *
  83.      * <p>
  84.      * The resulting DBDate will be set as having the value provided but will not
  85.      * be defined in the database.
  86.      *
  87.      * @param date  date
  88.      */
  89.     public DBInstant(Instant date) {
  90.         super(date);
  91.     }

  92.     /**
  93.      * Creates a column expression with a date result from the expression
  94.      * provided.
  95.      *
  96.      * <p>
  97.      * Used in {@link DBReport}, and some {@link DBRow}, sub-classes to derive
  98.      * data from the database prior to retrieval.
  99.      *
  100.      * @param dateExpression    dateExpression
  101.      */
  102.     public DBInstant(InstantExpression dateExpression) {
  103.         super(dateExpression);
  104.     }

  105.     /**
  106.      * Creates a DBDate with the value provided.
  107.      *
  108.      * <p>
  109.      * The resulting DBDate will be set as having the value provided but will not
  110.      * be defined in the database.
  111.      *
  112.      *
  113.      */
  114.     DBInstant(Timestamp timestamp) {
  115.         super(timestamp == null ? null : timestamp.toInstant());
  116.         if (timestamp == null) {
  117.             this.setToNull();
  118.         } else {
  119.             setLiteralValue(timestamp.toInstant());
  120.         }
  121.     }

  122.     /**
  123.      * Creates a DBDate with the value provided.
  124.      *
  125.      * <p>
  126.      * The resulting DBDate will be set as having the value provided but will not
  127.      * be defined in the database.
  128.      *
  129.      * <p>
  130.      * The string is parsed using {@link Instant#parse(java.lang.CharSequence) }
  131.      * so please ensure your string matches the requirements of that method.
  132.      *
  133.      *
  134.      */
  135.     DBInstant(String dateAsAString) {
  136.         setLiteralValue(Instant.parse(dateAsAString.subSequence(0, dateAsAString.length())));
  137.     }

  138.     /**
  139.      * Returns the set value of this DBDate as a Java Instant instance.
  140.      *
  141.      * <p style="color: #F90;">Support DBvolution at
  142.      * <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
  143.      *
  144.      * @return the value as a Java Instant.
  145.      */
  146.     public Instant instantValue() {
  147.         if (getLiteralValue() instanceof Instant) {
  148.             return getLiteralValue();
  149.         } else {
  150.             return null;
  151.         }
  152.     }

  153.     /**
  154.      * Returns the set value of this DBDate as a Java LocalDateTime instance.
  155.      *
  156.      * <p style="color: #F90;">Support DBvolution at
  157.      * <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
  158.      *
  159.      * @return the value as a Java Instant.
  160.      */
  161.     public LocalDateTime localDateTimeValue() {
  162.         if (getLiteralValue() instanceof Instant) {
  163.             return getLiteralValue().atZone(ZoneId.systemDefault()).toLocalDateTime();
  164.         } else {
  165.             return null;
  166.         }
  167.     }

  168.     /**
  169.      * Returns the set value of this DBDate as a Java LocalDateTime instance.
  170.      *
  171.      * <p style="color: #F90;">Support DBvolution at
  172.      * <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
  173.      *
  174.      * @return the value as a Java Instant.
  175.      */
  176.     public LocalDate localDateValue() {
  177.         if (getLiteralValue() instanceof Instant) {
  178.             return getLiteralValue().atZone(ZoneId.systemDefault()).toLocalDate();
  179.         } else {
  180.             return null;
  181.         }
  182.     }

  183.     /**
  184.      * Returns the set value of this DBInstant as a Java ZonedDateTime instance.
  185.      *
  186.      * @param zoneId the Zone ID to represent the instant at.
  187.      * @return the value as a Java Instant.
  188.      */
  189.     public ZonedDateTime zonedDateTimeValue(ZoneId zoneId) {
  190.         if (getLiteralValue() instanceof Instant) {
  191.             return getLiteralValue().atZone(zoneId);
  192.         } else {
  193.             return null;
  194.         }
  195.     }

  196.     /**
  197.      * Returns the set value of this DBDate as a Java ZonedDateTime instance.
  198.      *
  199.      * <p style="color: #F90;">Support DBvolution at
  200.      * <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
  201.      *
  202.      * @return the value as a Java Instant.
  203.      */
  204.     public ZonedDateTime utcDateTimeValue() {
  205.         if (getLiteralValue() instanceof Instant) {
  206.             return getLiteralValue().atZone(ZoneOffset.UTC);
  207.         } else {
  208.             return null;
  209.         }
  210.     }

  211.     void setValue(DBInstant newLiteralValue) {
  212.         setValue(newLiteralValue.getLiteralValue());
  213.     }

  214.     /**
  215.      * Sets the value of this QDT to the Java Instant provided.
  216.      *
  217.      * @param date  date
  218.      */
  219.     @Override
  220.     public void setValue(Instant date) {
  221.         super.setLiteralValue(date);
  222.     }

  223.     /**
  224.      * Sets the value of this QDT to the Java Instant provided.
  225.      *
  226.      * <p>
  227.      * The local date and time is moved to UTC before storing.</p>
  228.      *
  229.      * @param date  date
  230.      */
  231.     public void setValue(GregorianCalendar date) {
  232.         super.setLiteralValue(date.toZonedDateTime().withZoneSameLocal(ZoneOffset.UTC).toInstant());
  233.     }

  234.     /**
  235.      * Sets the value of this QDT to the Java Instant provided.
  236.      *
  237.      * <p>
  238.      * The local date and time is moved to UTC before storing.</p>
  239.      *
  240.      * @param date  date
  241.      */
  242.     public void setValue(Date date) {
  243.         super.setLiteralValue(date.toInstant());
  244.     }

  245.     /**
  246.      * Sets the value of this QDT to the Java LocalDateTime provided.
  247.      *
  248.      * <p>
  249.      * The local date and time is moved to UTC before storing.</p>
  250.      *
  251.      * @param date  date
  252.      */
  253.     public void setValue(LocalDateTime date) {
  254.         super.setLiteralValue(asInstant(date));
  255.     }

  256.     /**
  257.      * Sets the value of this QDT to the Java Instant provided.
  258.      *
  259.      * <p>
  260.      * The zoned date and time is stored as the equivalent UTC instant before
  261.      * storing.</p>
  262.      *
  263.      * @param date  date
  264.      */
  265.     public void setValue(ZonedDateTime date) {
  266.         super.setLiteralValue(date.toInstant());
  267.     }

  268.     /**
  269.      * Sets the value of this QDT to the date and time now.
  270.      *
  271.      */
  272.     public void setValueToNow() {
  273.         super.setValue(Instant.now());
  274.     }

  275.     /**
  276.      * Sets the value of this QDT to the dateStr provided.
  277.      *
  278.      * <p>
  279.      * The date String will be parsed by {@link Instant#parse(java.lang.CharSequence)
  280.      * }. so please confirms to the requirements of that method.
  281.      *
  282.      * @param dateStr   dateStr
  283.      */
  284.     public void setValue(String dateStr) {
  285.         setValue(Instant.parse(dateStr.subSequence(0, dateStr.length())));
  286.     }

  287.     @Override
  288.     public String getSQLDatatype() {
  289.         return "TIMESTAMP WITH TIME ZONE";
  290.     }

  291.     /**
  292.      * Returns the string value of the DBInstant.
  293.      *
  294.      * @return a string version of the current value of this DBDate
  295.      */
  296.     @Override
  297.     public String toString() {
  298.         if (this.isNull() || getValue() == null) {
  299.             return "<NULL>";
  300.         }
  301.         return DateTimeFormatter.ISO_INSTANT.format(getValue().atZone(ZoneId.of("Z")));
  302.     }

  303.     @Override
  304.     public String formatValueForSQLStatement(DBDefinition db) {
  305.         return db.getInstantFormattedForQuery(getValue());
  306.     }

  307.     @Override
  308.     protected Instant getFromResultSet(DBDefinition defn, ResultSet resultSet, String fullColumnName) {
  309.         Instant dbValue;
  310.         if (defn.prefersInstantsReadAsStrings()) {
  311.             dbValue = setByGetString(defn, resultSet, fullColumnName);
  312.         } else {
  313.             dbValue = setByGetTimestamp(defn, resultSet, fullColumnName);
  314.         }
  315.         return dbValue;
  316.     }

  317.     private Instant setByGetString(DBDefinition database, ResultSet resultSet, String fullColumnName) {
  318.         String string = null;
  319.         try {
  320.             string = resultSet.getString(fullColumnName);
  321.         } catch (SQLException sqlex) {
  322.             throw new DBRuntimeException("Unable to get Instant from String:" + sqlex.getLocalizedMessage(), sqlex);
  323.         }
  324.         if (string == null || string.isEmpty()) {
  325.             return null;
  326.         } else {
  327.             return database.parseInstantFromGetString(string);
  328.         }
  329.     }

  330.     private Instant setByGetTimestamp(DBDefinition defn, ResultSet resultSet, String fullColumnName) {
  331.         Instant dbValue = null;
  332.         try {
  333.             final Timestamp timestamp = resultSet.getTimestamp(fullColumnName);
  334.             if (resultSet.wasNull()) {
  335.                 dbValue = null;
  336.             } else {
  337.                 Instant utcVersion;
  338.                 if (defn.supportsTimeZones()) {
  339.                     utcVersion = timestamp.toInstant();
  340.                 } else {
  341.                     utcVersion = timestamp.toLocalDateTime().atZone(ZoneOffset.UTC).toInstant();
  342.                 }
  343.                 dbValue = utcVersion;
  344.             }
  345.         } catch (SQLException sqlex) {
  346.             throw new DBRuntimeException("Unable to set Instant by getting Instant: " + sqlex.getLocalizedMessage(), sqlex);
  347.         }
  348.         return dbValue;
  349.     }

  350.     @Override
  351.     public DBInstant copy() {
  352.         return (DBInstant) super.copy(); //To change body of generated methods, choose Tools | Templates.
  353.     }

  354.     @Override
  355.     public Instant getValue() {
  356.         return instantValue();
  357.     }

  358.     @Override
  359.     public DBInstant getQueryableDatatypeForExpressionValue() {
  360.         return new DBInstant();
  361.     }

  362.     @Override
  363.     public boolean isAggregator() {
  364.         return false;
  365.     }

  366.     @Override
  367.     public Set<DBRow> getTablesInvolved() {
  368.         return new HashSet<>();
  369.     }

  370.     /**
  371.      *
  372.      * reduces the rows to only the object, Set, List, Array, or vararg of objects
  373.      *
  374.      * @param permitted permitted
  375.      */
  376.     public void permittedValues(Instant... permitted) {
  377.         this.setOperator(new DBPermittedValuesOperator<Instant>(permitted));
  378.     }

  379.     /**
  380.      *
  381.      * reduces the rows to only the object, Set, List, Array, or vararg of objects
  382.      *
  383.      * @param permitted permitted
  384.      */
  385.     public void permittedValues(LocalDateTime... permitted) {
  386.         List<Instant> collect = asInstantList(permitted);
  387.         this.setOperator(new DBPermittedValuesOperator<Instant>(collect));
  388.     }

  389.     private List<Instant> asInstantList(LocalDateTime[] permitted) {
  390.         return Arrays.asList(permitted).stream().map((t) -> asInstant(t)).collect(Collectors.toList());
  391.     }

  392.     private static Instant asInstant(LocalDateTime t) {
  393.         return t.toInstant(ZoneOffset.UTC);
  394.     }

  395.     /**
  396.      *
  397.      * excludes the object, Set, List, Array, or vararg of objects
  398.      *
  399.      *
  400.      * @param excluded  excluded
  401.      */
  402.     public void excludedValues(Instant... excluded) {
  403.         this.setOperator(new DBPermittedValuesOperator<Instant>(excluded));
  404.         negateOperator();
  405.     }

  406.     /**
  407.      *
  408.      * excludes the object, Set, List, Array, or vararg of objects
  409.      *
  410.      *
  411.      * @param excluded  excluded
  412.      */
  413.     public void excludedValues(LocalDateTime... excluded) {
  414.         List<Instant> list = asInstantList(excluded);
  415.         this.setOperator(new DBPermittedValuesOperator<Instant>(list));
  416.         negateOperator();
  417.     }

  418.     /**
  419.      * Performs searches based on a range.
  420.      *
  421.      * if both ends of the range are specified the lower-bound will be included in
  422.      * the search and the upper-bound excluded. I.e permittedRange(1,3) will
  423.      * return 1 and 2.
  424.      *
  425.      * <p>
  426.      * if the upper-bound is null the range will be open ended upwards and
  427.      * inclusive.
  428.      * <br>
  429.      * I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
  430.      *
  431.      * <p>
  432.      * if the lower-bound is null the range will be open ended downwards and
  433.      * exclusive.
  434.      * <br>
  435.      * I.e permittedRange(null, 5) will return 4,3,2,1, etc.
  436.      *
  437.      * @param lowerBound lowerBound
  438.      * @param upperBound upperBound
  439.      */
  440.     public void permittedRange(Instant lowerBound, Instant upperBound) {
  441.         setOperator(new DBPermittedRangeOperator<Instant>(lowerBound, upperBound));
  442.     }

  443.     /**
  444.      * Performs searches based on a range.
  445.      *
  446.      * if both ends of the range are specified the lower-bound will be included in
  447.      * the search and the upper-bound excluded. I.e permittedRange(1,3) will
  448.      * return 1 and 2.
  449.      *
  450.      * <p>
  451.      * if the upper-bound is null the range will be open ended upwards and
  452.      * inclusive.
  453.      * <br>
  454.      * I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
  455.      *
  456.      * <p>
  457.      * if the lower-bound is null the range will be open ended downwards and
  458.      * exclusive.
  459.      * <br>
  460.      * I.e permittedRange(null, 5) will return 4,3,2,1, etc.
  461.      *
  462.      * @param lowerBound lowerBound
  463.      * @param upperBound upperBound
  464.      */
  465.     public void permittedRange(LocalDateTime lowerBound, LocalDateTime upperBound) {
  466.         setOperator(new DBPermittedRangeOperator<Instant>(asInstant(lowerBound), asInstant(upperBound)));
  467.     }

  468.     /**
  469.      * Performs searches based on a range.
  470.      *
  471.      * if both ends of the range are specified both the lower- and upper-bound
  472.      * will be included in the search. I.e permittedRangeInclusive(1,3) will
  473.      * return 1, 2, and 3.
  474.      *
  475.      * <p>
  476.      * if the upper-bound is null the range will be open ended upwards and
  477.      * inclusive.
  478.      * <br>
  479.      * I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
  480.      *
  481.      * <p>
  482.      * if the upper-bound is null the range will be open ended downwards and
  483.      * inclusive.
  484.      * <br>
  485.      * I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
  486.      *
  487.      * @param lowerBound lowerBound
  488.      * @param upperBound upperBound
  489.      */
  490.     public void permittedRangeInclusive(Instant lowerBound, Instant upperBound) {
  491.         setOperator(new DBPermittedRangeInclusiveOperator(lowerBound, upperBound));
  492.     }

  493.     /**
  494.      * Performs searches based on a range.
  495.      *
  496.      * if both ends of the range are specified both the lower- and upper-bound
  497.      * will be included in the search. I.e permittedRangeInclusive(1,3) will
  498.      * return 1, 2, and 3.
  499.      *
  500.      * <p>
  501.      * if the upper-bound is null the range will be open ended upwards and
  502.      * inclusive.
  503.      * <br>
  504.      * I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
  505.      *
  506.      * <p>
  507.      * if the upper-bound is null the range will be open ended downwards and
  508.      * inclusive.
  509.      * <br>
  510.      * I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
  511.      *
  512.      * @param lowerBound lowerBound
  513.      * @param upperBound upperBound
  514.      */
  515.     public void permittedRangeInclusive(LocalDateTime lowerBound, LocalDateTime upperBound) {
  516.         setOperator(new DBPermittedRangeInclusiveOperator(asInstant(lowerBound), asInstant(upperBound)));
  517.     }

  518.     /**
  519.      * Performs searches based on a range.
  520.      *
  521.      * if both ends of the range are specified both the lower- and upper-bound
  522.      * will be excluded in the search. I.e permittedRangeExclusive(1,3) will
  523.      * return 2.
  524.      *
  525.      * <p>
  526.      * if the upper-bound is null the range will be open ended upwards and
  527.      * exclusive.
  528.      * <br>
  529.      * I.e permittedRangeExclusive(1,null) will return 2,3,4,5,...
  530.      *
  531.      * <p>
  532.      * if the upper-bound is null the range will be open ended downwards and
  533.      * exclusive.
  534.      * <br>
  535.      * I.e permittedRangeExclusive(null, 5) will return 4,3,2,1,...
  536.      *
  537.      * @param lowerBound lowerBound
  538.      * @param upperBound upperBound
  539.      */
  540.     public void permittedRangeExclusive(Instant lowerBound, Instant upperBound) {
  541.         setOperator(new DBPermittedRangeExclusiveOperator(lowerBound, upperBound));
  542.     }

  543.     /**
  544.      * Performs searches based on a range.
  545.      *
  546.      * if both ends of the range are specified both the lower- and upper-bound
  547.      * will be excluded in the search. I.e permittedRangeExclusive(1,3) will
  548.      * return 2.
  549.      *
  550.      * <p>
  551.      * if the upper-bound is null the range will be open ended upwards and
  552.      * exclusive.
  553.      * <br>
  554.      * I.e permittedRangeExclusive(1,null) will return 2,3,4,5,...
  555.      *
  556.      * <p>
  557.      * if the upper-bound is null the range will be open ended downwards and
  558.      * exclusive.
  559.      * <br>
  560.      * I.e permittedRangeExclusive(null, 5) will return 4,3,2,1,...
  561.      *
  562.      * @param lowerBound lowerBound
  563.      * @param upperBound upperBound
  564.      */
  565.     public void permittedRangeExclusive(LocalDateTime lowerBound, LocalDateTime upperBound) {
  566.         setOperator(new DBPermittedRangeExclusiveOperator(asInstant(lowerBound), asInstant(upperBound)));
  567.     }

  568.     /**
  569.      * Performs searches based on a range.
  570.      *
  571.      * if both ends of the range are specified the lower-bound will be included in
  572.      * the search and the upper-bound excluded. I.e excludedRange(1,3) will return
  573.      * everything except 1 and 2.
  574.      *
  575.      * <p>
  576.      * if the upper-bound is null the range will be open ended upwards and
  577.      * inclusive.
  578.      * <br>
  579.      * I.e excludedRange(1,null) will return ..., -1, 0.
  580.      *
  581.      * <p>
  582.      * if the lower-bound is null the range will be open ended downwards and
  583.      * exclusive.
  584.      * <br>
  585.      * I.e excludedRange(null, 5) will return 5, 6, 7, 8 etc.
  586.      *
  587.      * @param lowerBound lowerBound
  588.      * @param upperBound upperBound
  589.      */
  590.     public void excludedRange(Instant lowerBound, Instant upperBound) {
  591.         setOperator(new DBPermittedRangeOperator<Instant>(lowerBound, upperBound));
  592.         negateOperator();
  593.     }

  594.     /**
  595.      * Performs searches based on a range.
  596.      *
  597.      * if both ends of the range are specified the lower-bound will be included in
  598.      * the search and the upper-bound excluded. I.e excludedRange(1,3) will return
  599.      * everything except 1 and 2.
  600.      *
  601.      * <p>
  602.      * if the upper-bound is null the range will be open ended upwards and
  603.      * inclusive.
  604.      * <br>
  605.      * I.e excludedRange(1,null) will return ..., -1, 0.
  606.      *
  607.      * <p>
  608.      * if the lower-bound is null the range will be open ended downwards and
  609.      * exclusive.
  610.      * <br>
  611.      * I.e excludedRange(null, 5) will return 5, 6, 7, 8 etc.
  612.      *
  613.      * @param lowerBound lowerBound
  614.      * @param upperBound upperBound
  615.      */
  616.     public void excludedRange(LocalDateTime lowerBound, LocalDateTime upperBound) {
  617.         setOperator(new DBPermittedRangeOperator<Instant>(asInstant(lowerBound), asInstant(upperBound)));
  618.         negateOperator();
  619.     }

  620.     /**
  621.      * Performs searches based on a range.
  622.      *
  623.      * if both ends of the range are specified both the lower- and upper-bound
  624.      * will be included in the search. I.e excludedRangeInclusive(1,3) will return
  625.      * ..., -1, 0, 4, 5, ... .
  626.      *
  627.      * <p>
  628.      * if the upper-bound is null the range will be open ended upwards and
  629.      * inclusive.
  630.      * <br>
  631.      * I.e excludedRangeInclusive(1,null) will return ..., -1, 0.
  632.      *
  633.      * <p>
  634.      * if the upper-bound is null the range will be open ended downwards and
  635.      * inclusive.
  636.      * <br>
  637.      * I.e excludedRangeInclusive(null, 5) will return 6, 7, 8, 9,... etc.
  638.      *
  639.      * @param lowerBound lowerBound
  640.      * @param upperBound upperBound
  641.      */
  642.     public void excludedRangeInclusive(Instant lowerBound, Instant upperBound) {
  643.         setOperator(new DBPermittedRangeInclusiveOperator(lowerBound, upperBound));
  644.         negateOperator();
  645.     }

  646.     /**
  647.      * Performs searches based on a range.
  648.      *
  649.      * if both ends of the range are specified both the lower- and upper-bound
  650.      * will be included in the search. I.e excludedRangeInclusive(1,3) will return
  651.      * ..., -1, 0, 4, 5, ... .
  652.      *
  653.      * <p>
  654.      * if the upper-bound is null the range will be open ended upwards and
  655.      * inclusive.
  656.      * <br>
  657.      * I.e excludedRangeInclusive(1,null) will return ..., -1, 0.
  658.      *
  659.      * <p>
  660.      * if the upper-bound is null the range will be open ended downwards and
  661.      * inclusive.
  662.      * <br>
  663.      * I.e excludedRangeInclusive(null, 5) will return 6, 7, 8, 9,... etc.
  664.      *
  665.      * @param lowerBound lowerBound
  666.      * @param upperBound upperBound
  667.      */
  668.     public void excludedRangeInclusive(LocalDateTime lowerBound, LocalDateTime upperBound) {
  669.         setOperator(new DBPermittedRangeInclusiveOperator(asInstant(lowerBound), asInstant(upperBound)));
  670.         negateOperator();
  671.     }

  672.     /**
  673.      * Performs searches based on a range.
  674.      *
  675.      * if both ends of the range are specified both the lower- and upper-bound
  676.      * will be excluded in the search. I.e excludedRangeExclusive(1,3) will return
  677.      * ... -1, 0, 1, 3, 4,... but exclude 2.
  678.      *
  679.      * <p>
  680.      * if the upper-bound is null the range will be open ended upwards and
  681.      * exclusive.
  682.      * <br>
  683.      * I.e excludedRangeExclusive(1,null) will return ..., -1 ,0 ,1 .
  684.      *
  685.      * <p>
  686.      * if the upper-bound is null the range will be open ended downwards and
  687.      * exclusive.
  688.      * <br>
  689.      * I.e excludedRangeExclusive(null, 5) will return 5,6,7,8...
  690.      *
  691.      * @param lowerBound lowerBound
  692.      * @param upperBound upperBound
  693.      */
  694.     public void excludedRangeExclusive(Instant lowerBound, Instant upperBound) {
  695.         setOperator(new DBPermittedRangeExclusiveOperator(lowerBound, upperBound));
  696.         negateOperator();
  697.     }

  698.     /**
  699.      * Performs searches based on a range.
  700.      *
  701.      * if both ends of the range are specified both the lower- and upper-bound
  702.      * will be excluded in the search. I.e excludedRangeExclusive(1,3) will return
  703.      * ... -1, 0, 1, 3, 4,... but exclude 2.
  704.      *
  705.      * <p>
  706.      * if the upper-bound is null the range will be open ended upwards and
  707.      * exclusive.
  708.      * <br>
  709.      * I.e excludedRangeExclusive(1,null) will return ..., -1 ,0 ,1 .
  710.      *
  711.      * <p>
  712.      * if the upper-bound is null the range will be open ended downwards and
  713.      * exclusive.
  714.      * <br>
  715.      * I.e excludedRangeExclusive(null, 5) will return 5,6,7,8...
  716.      *
  717.      * @param lowerBound lowerBound
  718.      * @param upperBound upperBound
  719.      */
  720.     public void excludedRangeExclusive(LocalDateTime lowerBound, LocalDateTime upperBound) {
  721.         setOperator(new DBPermittedRangeExclusiveOperator(asInstant(lowerBound), asInstant(upperBound)));
  722.         negateOperator();
  723.     }

  724.     /**
  725.      *
  726.      * reduces the rows to only the object, Set, List, Array, or vararg of objects
  727.      *
  728.      * @param permitted permitted
  729.      */
  730.     public void permittedValues(InstantExpression... permitted) {
  731.         this.setOperator(new DBPermittedValuesOperator<InstantExpression>(permitted));
  732.     }

  733.     /**
  734.      *
  735.      * excludes the object, Set, List, Array, or vararg of objects
  736.      *
  737.      *
  738.      * @param excluded  excluded
  739.      */
  740.     public void excludedValues(InstantExpression... excluded) {
  741.         this.setOperator(new DBPermittedValuesOperator<InstantExpression>(excluded));
  742.         negateOperator();
  743.     }

  744.     /**
  745.      * Performs searches based on a range.
  746.      *
  747.      * if both ends of the range are specified the lower-bound will be included in
  748.      * the search and the upper-bound excluded. I.e permittedRange(1,3) will
  749.      * return 1 and 2.
  750.      *
  751.      * <p>
  752.      * if the upper-bound is null the range will be open ended upwards and
  753.      * inclusive.
  754.      * <br>
  755.      * I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
  756.      *
  757.      * <p>
  758.      * if the lower-bound is null the range will be open ended downwards and
  759.      * exclusive.
  760.      * <br>
  761.      * I.e permittedRange(null, 5) will return 4,3,2,1, etc.
  762.      *
  763.      * @param lowerBound lowerBound
  764.      * @param upperBound upperBound
  765.      */
  766.     public void permittedRange(InstantExpression lowerBound, InstantExpression upperBound) {
  767.         setOperator(new DBPermittedRangeOperator<InstantExpression>(lowerBound, upperBound));
  768.     }

  769.     /**
  770.      * Performs searches based on a range.
  771.      *
  772.      * if both ends of the range are specified both the lower- and upper-bound
  773.      * will be included in the search. I.e permittedRangeInclusive(1,3) will
  774.      * return 1, 2, and 3.
  775.      *
  776.      * <p>
  777.      * if the upper-bound is null the range will be open ended upwards and
  778.      * inclusive.
  779.      * <br>
  780.      * I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
  781.      *
  782.      * <p>
  783.      * if the lower-bound is null the range will be open ended downwards and
  784.      * inclusive.
  785.      * <br>
  786.      * I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
  787.      *
  788.      * @param lowerBound lowerBound
  789.      * @param upperBound upperBound
  790.      */
  791.     public void permittedRangeInclusive(InstantExpression lowerBound, InstantExpression upperBound) {
  792.         setOperator(new DBPermittedRangeInclusiveOperator(lowerBound, upperBound));
  793.     }

  794.     /**
  795.      * Performs searches based on a range.
  796.      *
  797.      * if both ends of the range are specified both the lower- and upper-bound
  798.      * will be excluded in the search. I.e permittedRangeExclusive(1,3) will
  799.      * return 2.
  800.      *
  801.      * <p>
  802.      * if the upper-bound is null the range will be open ended upwards and
  803.      * exclusive.
  804.      * <br>
  805.      * I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc.
  806.      *
  807.      * <p>
  808.      * if the lower-bound is null the range will be open ended downwards and
  809.      * exclusive.
  810.      * <br>
  811.      * I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc.
  812.      *
  813.      * @param lowerBound lowerBound
  814.      * @param upperBound upperBound
  815.      */
  816.     public void permittedRangeExclusive(InstantExpression lowerBound, InstantExpression upperBound) {
  817.         setOperator(new DBPermittedRangeExclusiveOperator(lowerBound, upperBound));
  818.     }

  819.     /**
  820.      * Performs searches based on a range.
  821.      *
  822.      * if both ends of the range are specified the lower-bound will be included in
  823.      * the search and the upper-bound excluded. I.e excludedRange(1,3) will return
  824.      * everything except 1 and 2.
  825.      *
  826.      * <p>
  827.      * if the upper-bound is null the range will be open ended upwards and
  828.      * inclusive.
  829.      * <br>
  830.      * I.e excludedRange(1,null) will return 0, -1, -2, etc.
  831.      *
  832.      * <p>
  833.      * if the lower-bound is null the range will be open ended downwards and
  834.      * exclusive.
  835.      * <br>
  836.      * I.e excludedRange(null, 5) will return 5, 6, 7, 8, etc.
  837.      *
  838.      * @param lowerBound lowerBound
  839.      * @param upperBound upperBound
  840.      */
  841.     public void excludedRange(InstantExpression lowerBound, InstantExpression upperBound) {
  842.         setOperator(new DBPermittedRangeOperator<InstantExpression>(lowerBound, upperBound));
  843.         negateOperator();
  844.     }

  845.     /**
  846.      * Performs searches based on a range.
  847.      *
  848.      * if both ends of the range are specified both the lower- and upper-bound
  849.      * will be included in the search. I.e excludedRangeInclusive(1,3) will return
  850.      * everything except 1, 2, and 3.
  851.      *
  852.      * <p>
  853.      * if the upper-bound is null the range will be open ended upwards and
  854.      * inclusive.
  855.      * <br>
  856.      * I.e excludedRangeInclusive(1,null) will return ..., -1, 0.
  857.      *
  858.      * <p>
  859.      * if the lower-bound is null the range will be open ended downwards and
  860.      * inclusive.
  861.      * <br>
  862.      * I.e excludedRangeInclusive(null, 5) will return 6, 7, 8, 9, etc.
  863.      *
  864.      * @param lowerBound lowerBound
  865.      * @param upperBound upperBound
  866.      */
  867.     public void excludedRangeInclusive(InstantExpression lowerBound, InstantExpression upperBound) {
  868.         setOperator(new DBPermittedRangeInclusiveOperator(lowerBound, upperBound));
  869.         negateOperator();
  870.     }

  871.     /**
  872.      * Performs searches based on a range.
  873.      *
  874.      * if both ends of the range are specified both the lower- and upper-bound
  875.      * will be excluded in the search. I.e excludedRangeExclusive(1,3) will return
  876.      * everything except 2.
  877.      *
  878.      * <p>
  879.      * if the upper-bound is null the range will be open ended upwards and
  880.      * exclusive.
  881.      * <br>
  882.      * I.e excludedRangeExclusive(1,null) will return 0, -1, -2, etc.
  883.      *
  884.      * <p>
  885.      * if the lower-bound is null the range will be open ended downwards and
  886.      * exclusive.
  887.      * <br>
  888.      * I.e excludedRangeExclusive(null, 5) will return 5, 6, 7, 8,, etc.
  889.      *
  890.      * @param lowerBound lowerBound
  891.      * @param upperBound upperBound
  892.      */
  893.     public void excludedRangeExclusive(InstantExpression lowerBound, InstantExpression upperBound) {
  894.         setOperator(new DBPermittedRangeExclusiveOperator(lowerBound, upperBound));
  895.         negateOperator();
  896.     }

  897.     /**
  898.      * Used internally to decide whether the required query needs to include NULL
  899.      * values.
  900.      *
  901.      * <p style="color: #F90;">Support DBvolution at
  902.      * <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
  903.      *
  904.      * @return whether the query expression needs to test for NULL.
  905.      */
  906.     @Override
  907.     public boolean getIncludesNull() {
  908.         return getValue() == null;
  909.     }

  910.     @Override
  911.     protected void setValueFromStandardStringEncoding(String encodedValue) {
  912.         throw new UnsupportedOperationException("DBInstant Does Not Have An Accepted Standard String"); //To change body of generated methods, choose Tools | Templates.
  913.     }

  914.     @Override
  915.     public InstantColumn getColumn(RowDefinition row) throws IncorrectRowProviderInstanceSuppliedException {
  916.         return new InstantColumn(row, this);
  917.     }

  918.     @Override
  919.     public StringExpression stringResult() {
  920.         return new InstantExpression(this).stringResult();
  921.     }

  922.     public void excludeNotNull() {
  923.         this.permittedValues((Instant) null);
  924.     }

  925.     public void excludeNull() {
  926.         this.excludedValues((Instant) null);
  927.     }

  928.     public void permitOnlyNull() {
  929.         excludeNotNull();
  930.     }

  931.     public void permitOnlyNotNull() {
  932.         excludeNull();
  933.     }

  934.     /**
  935.      * Set the value to be inserted when no value has been set, using
  936.      * {@link #setValue(java.time.LocalDateTime)  setValue(...)}, for the QDT.
  937.      *
  938.      * <p>
  939.      * The value is only used during the initial insert and does not effect the
  940.      * definition of the column within the database.</p>
  941.      *
  942.      * <p>
  943.      * Correct usages for standard date defaults:
  944.      *
  945.      * <pre>
  946.      * &#64;DBColumn
  947.      * public DBDate creationDate = new DBDate().setDefaultInsertValue(DateExpression.currentDate());
  948.      *
  949.      * &#64;DBColumn
  950.      * public DBDate updateDate = new DBDate().setDefaultUpdateValue(DateExpression.currentDate());
  951.      *
  952.      * &#64;DBColumn
  953.      * public DBDate creationOrUpdateDate = new DBDate()
  954.      * .setDefaultInsertValue(DateExpression.currentDate())
  955.      * .setDefaultUpdateValue(DateExpression.currentDate());
  956.      * </pre>
  957.      *
  958.      * @param value the value to use during insertion when no particular value has
  959.      * been specified.
  960.      * @return This QDT
  961.      */
  962.     @Override
  963.     public synchronized DBInstant setDefaultInsertValue(Instant value) {
  964.         super.setDefaultInsertValue(value);
  965.         return this;
  966.     }

  967.     /**
  968.      * Set the value to be inserted when no value has been set, using
  969.      * {@link #setValue(java.time.LocalDateTime)  setValue(...)}, for the QDT.
  970.      *
  971.      * <p>
  972.      * The value is only used during the initial insert and does not effect the
  973.      * definition of the column within the database.</p>
  974.      *
  975.      * <p>
  976.      * Care should be taken when using this as some "obvious" uses are better
  977.      * handled using the
  978.      * {@link #setDefaultInsertValue(nz.co.gregs.dbvolution.results.AnyResult) expression version}.
  979.      * In particular, setDefaultInsertValue(new Instant()) is probably NOT what
  980.      * you want, setDefaultInsertValue(DateExpression.currentDate()) will produce
  981.      * a correct creation date value.</p>
  982.      *
  983.      * <p>
  984.      * Correct usages for standard date defaults:
  985.      *
  986.      * <pre>
  987.      * &#64;DBColumn
  988.      * public DBDate creationDate = new DBDate().setDefaultInsertValue(DateExpression.currentDate());
  989.      *
  990.      * &#64;DBColumn
  991.      * public DBDate updateDate = new DBDate().setDefaultUpdateValue(DateExpression.currentDate());
  992.      *
  993.      * &#64;DBColumn
  994.      * public DBDate creationOrUpdateDate = new DBDate()
  995.      * .setDefaultInsertValue(DateExpression.currentDate())
  996.      * .setDefaultUpdateValue(DateExpression.currentDate());
  997.      * </pre>
  998.      *
  999.      * @param value the value to use during insertion when no particular value has
  1000.      * been specified.
  1001.      * @return This QDT
  1002.      */
  1003.     public synchronized DBInstant setDefaultInsertValue(InstantResult value) {
  1004.         super.setDefaultInsertValue(value);
  1005.         return this;
  1006.     }

  1007.     /**
  1008.      * Set the value to be used during an update when no value has been set, using
  1009.      * {@link #setValue(java.time.LocalDateTime)   setValue(...)}, for the QDT.
  1010.      *
  1011.      * <p>
  1012.      * The value is only used during updates and does not effect the definition of
  1013.      * the column within the database nor the initial value of the column.</p>
  1014.      *
  1015.      * <p>
  1016.      * Care should be taken when using this as some "obvious" uses are better
  1017.      * handled using the
  1018.      * {@link #setDefaultUpdateValue(nz.co.gregs.dbvolution.results.AnyResult) expression version}.
  1019.      * In particular, setDefaultUpdateValue(new Instant()) is probably NOT what
  1020.      * you want, setDefaultUpdateValue(DateExpression.currentDate()) will produce
  1021.      * a correct update time value.</p>
  1022.      *
  1023.      * <p>
  1024.      * Correct usages for standard date defaults:
  1025.      *
  1026.      * <pre>
  1027.      * &#64;DBColumn
  1028.      * public DBDate creationDate = new DBDate().setDefaultInsertValue(DateExpression.currentDate());
  1029.      *
  1030.      * &#64;DBColumn
  1031.      * public DBDate updateDate = new DBDate().setDefaultUpdateValue(DateExpression.currentDate());
  1032.      *
  1033.      * &#64;DBColumn
  1034.      * public DBDate creationOrUpdateDate = new DBDate()
  1035.      * .setDefaultInsertValue(DateExpression.currentDate())
  1036.      * .setDefaultUpdateValue(DateExpression.currentDate());
  1037.      * </pre>
  1038.      *
  1039.      * @param value the value to use during update when no particular value has
  1040.      * been specified.
  1041.      * @return This QDT
  1042.      */
  1043.     @Override
  1044.     public synchronized DBInstant setDefaultUpdateValue(Instant value) {
  1045.         super.setDefaultUpdateValue(value);
  1046.         return this;
  1047.     }

  1048.     /**
  1049.      * Set the value to be used during an update when no value has been set, using
  1050.      * {@link #setValue(java.time.LocalDateTime)   setValue(...)}, for the QDT.
  1051.      *
  1052.      * <p>
  1053.      * The value is only used during updates and does not effect the definition of
  1054.      * the column within the database nor the initial value of the column.</p>
  1055.      *
  1056.      * <p>
  1057.      * Correct usages for standard date defaults:
  1058.      *
  1059.      * <pre>
  1060.      * &#64;DBColumn
  1061.      * public DBDate creationDate = new DBDate().setDefaultInsertValue(DateExpression.currentDate());
  1062.      *
  1063.      * &#64;DBColumn
  1064.      * public DBDate updateDate = new DBDate().setDefaultUpdateValue(DateExpression.currentDate());
  1065.      *
  1066.      * &#64;DBColumn
  1067.      * public DBDate creationOrUpdateDate = new DBDate()
  1068.      * .setDefaultInsertValue(DateExpression.currentDate())
  1069.      * .setDefaultUpdateValue(DateExpression.currentDate());
  1070.      * </pre>
  1071.      *
  1072.      * @param value the value to use during update when no particular value has
  1073.      * been specified.
  1074.      * @return This QDT
  1075.      */
  1076.     public synchronized DBInstant setDefaultUpdateValue(InstantResult value) {
  1077.         super.setDefaultUpdateValue(value);
  1078.         return this;
  1079.     }

  1080.     public void permitOnlyPastAndPresent() {
  1081.         this.setOperator(new DBLessThanOrEqualOperator(InstantExpression.now()));
  1082.     }

  1083.     public void permitOnlyPresentAndFuture() {
  1084.         this.setOperator(new DBGreaterThanOrEqualsOperator(InstantExpression.now()));
  1085.     }

  1086.     public void permitOnlyPast() {
  1087.         this.setOperator(new DBLessThanOperator(InstantExpression.currentDate()));
  1088.     }

  1089.     public void permitOnlyFuture() {
  1090.         this.setOperator(new DBGreaterThanOperator(InstantExpression.currentDate()));
  1091.     }

  1092.     public void permitOnlyPastAndPresentByDateOnly() {
  1093.         this.setOperator(new DBLessThanOrEqualOperator(InstantExpression.currentDateOnly()));
  1094.     }

  1095.     public void permitOnlyPresentAndFutureByDateOnly() {
  1096.         this.setOperator(new DBGreaterThanOrEqualsOperator(InstantExpression.currentDateOnly()));
  1097.     }

  1098.     public void permitOnlyPastByDateOnly() {
  1099.         this.setOperator(new DBLessThanOperator(InstantExpression.currentDateOnly()));
  1100.     }

  1101.     public void permitOnlyFutureByDateOnly() {
  1102.         this.setOperator(new DBGreaterThanOperator(InstantExpression.currentDateOnly()));
  1103.     }

  1104.     public DBInstant setDefaultInsertValueToNow() {
  1105.         super.setDefaultInsertValue(Instant.now());
  1106.         return this;
  1107.     }

  1108.     public DBInstant setDefaultUpdateValueToNow() {
  1109.         super.setDefaultUpdateValue(Instant.now());
  1110.         return this;
  1111.     }

  1112.     @Override
  1113.     public Comparator<Instant> getComparator() {
  1114.         return ComparableComparator.forClass(Instant.class);
  1115.     }
  1116. }