001package io.ebeaninternal.server.type;
002
003import com.fasterxml.jackson.core.JsonGenerator;
004import com.fasterxml.jackson.core.JsonParser;
005import com.fasterxml.jackson.core.JsonToken;
006import io.ebean.config.JsonConfig;
007import io.ebeanservice.docstore.api.mapping.DocPropertyType;
008
009import java.io.DataInput;
010import java.io.DataOutput;
011import java.io.IOException;
012import java.sql.Date;
013import java.sql.SQLException;
014import java.sql.Types;
015
016/**
017 * Base class for Date types.
018 */
019public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
020
021  protected final JsonConfig.Date mode;
022
023  ScalarTypeBaseDate(JsonConfig.Date mode, Class<T> type, boolean jdbcNative, int jdbcType) {
024    super(type, jdbcNative, jdbcType);
025    this.mode = mode;
026  }
027
028  /**
029   * Convert the target value to millis.
030   */
031  public abstract long convertToMillis(T value);
032
033  /**
034   * Convert to java.sql.Date from the target Date type.
035   */
036  public abstract java.sql.Date convertToDate(T t);
037
038  /**
039   * Convert from java.sql.Date to the target Date type.
040   */
041  public abstract T convertFromDate(java.sql.Date ts);
042
043  @Override
044  public void bind(DataBind b, T value) throws SQLException {
045    if (value == null) {
046      b.setNull(Types.DATE);
047    } else {
048      b.setDate(convertToDate(value));
049    }
050  }
051
052  @Override
053  public T read(DataReader dataReader) throws SQLException {
054
055    Date ts = dataReader.getDate();
056    return ts == null ? null : convertFromDate(ts);
057  }
058
059  @Override
060  public String formatValue(T t) {
061    Date date = convertToDate(t);
062    // format all dates into epoch millis
063    long epochMillis = date.getTime();
064    return Long.toString(epochMillis);
065  }
066
067  @Override
068  public T parse(String value) {
069    try {
070      long epochMillis = Long.parseLong(value);
071      return convertFromDate(new Date(epochMillis));
072    } catch (NumberFormatException e) {
073      Date date = Date.valueOf(value);
074      return convertFromDate(date);
075    }
076  }
077
078  @Override
079  public T convertFromMillis(long systemTimeMillis) {
080    Date ts = new Date(systemTimeMillis);
081    return convertFromDate(ts);
082  }
083
084  @Override
085  public boolean isDateTimeCapable() {
086    return true;
087  }
088
089  @Override
090  public T jsonRead(JsonParser parser) throws IOException {
091    if (JsonToken.VALUE_NUMBER_INT == parser.getCurrentToken()) {
092      return convertFromMillis(parser.getLongValue());
093    } else {
094      return convertFromDate(Date.valueOf(parser.getText()));
095    }
096  }
097
098  @Override
099  public void jsonWrite(JsonGenerator writer, T value) throws IOException {
100    if (mode == JsonConfig.Date.ISO8601) {
101      writer.writeString(toIsoFormat(value));
102    } else {
103      writer.writeNumber(convertToMillis(value));
104    }
105  }
106
107  /**
108   * Convert the value to ISO8601 format.
109   */
110  protected abstract String toIsoFormat(T value);
111
112  @Override
113  public DocPropertyType getDocType() {
114    return DocPropertyType.DATE;
115  }
116
117  @Override
118  public T readData(DataInput dataInput) throws IOException {
119    if (!dataInput.readBoolean()) {
120      return null;
121    } else {
122      long val = dataInput.readLong();
123      Date date = new Date(val);
124      return convertFromDate(date);
125    }
126  }
127
128  @Override
129  public void writeData(DataOutput dataOutput, T value) throws IOException {
130
131    if (value == null) {
132      dataOutput.writeBoolean(false);
133    } else {
134      dataOutput.writeBoolean(true);
135      Date date = convertToDate(value);
136      dataOutput.writeLong(date.getTime());
137    }
138  }
139
140}