package io.dropwizard.jdbi.timestamps;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestRule;
import org.skife.jdbi.v2.Handle;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
import java.util.Random;
import java.util.TimeZone;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for handling translation between DateTime to SQL TIMESTAMP
* in a different time zone
*/
public class JodaDateTimeSqlTimestampTest {
private static final DateTimeFormatter ISO_FMT = ISODateTimeFormat.dateTimeNoMillis();
private static TemporaryFolder temporaryFolder;
private static DatabaseInTimeZone databaseInTimeZone;
private static DateTimeZone dbTimeZone;
private static DBIClient dbiClient;
@ClassRule
public static TestRule chain;
static {
boolean done = false;
while (!done) {
try {
final TimeZone timeZone = getRandomTimeZone();
dbTimeZone = DateTimeZone.forTimeZone(timeZone);
temporaryFolder = new TemporaryFolder();
databaseInTimeZone = new DatabaseInTimeZone(temporaryFolder, timeZone);
dbiClient = new DBIClient(timeZone);
chain = RuleChain.outerRule(temporaryFolder)
.around(databaseInTimeZone)
.around(dbiClient);
done = true;
} catch (IllegalArgumentException e) {
if (!e.getMessage().contains("is not recognised")) {
throw e;
}
}
}
}
private Handle handle;
private FlightDao flightDao;
private static TimeZone getRandomTimeZone() {
String[] ids = TimeZone.getAvailableIDs();
return TimeZone.getTimeZone(ids[new Random().nextInt(ids.length)]);
}
@Before
public void setUp() throws Exception {
handle = dbiClient.getDbi().open();
handle.execute("CREATE TABLE flights (" +
" flight_id VARCHAR(5) PRIMARY KEY," +
" departure_airport VARCHAR(3) NOT NULL," +
" arrival_airport VARCHAR(3) NOT NULL," +
" departure_time TIMESTAMP NOT NULL," +
" arrival_time TIMESTAMP NOT NULL" +
")");
flightDao = handle.attach(FlightDao.class);
}
@After
public void tearDown() throws Exception {
handle.execute("DROP TABLE flights");
handle.close();
}
@Test
public void testInsertTimestamp() {
final DateTime departureTime = ISO_FMT.parseDateTime("2015-04-01T06:00:00-05:00");
final DateTime arrivalTime = ISO_FMT.parseDateTime("2015-04-01T21:00:00+02:00");
final int result = flightDao.insert("C1671", "ORD", "DUS", departureTime, arrivalTime);
assertThat(result).isGreaterThan(0);
final Integer serverDepartureHour = (Integer) handle.select(
"SELECT EXTRACT(HOUR FROM departure_time) departure_hour " +
"FROM flights WHERE flight_id=?", "C1671").get(0).get("departure_hour");
final Integer serverArrivalHour = (Integer) handle.select(
"SELECT EXTRACT(HOUR FROM arrival_time) arrival_hour " +
"FROM flights WHERE flight_id=?", "C1671").get(0).get("arrival_hour");
assertThat(serverDepartureHour).isEqualTo(departureTime.withZone(dbTimeZone).getHourOfDay());
assertThat(serverArrivalHour).isEqualTo(arrivalTime.withZone(dbTimeZone).getHourOfDay());
}
@Test
public void testReadTimestamp() {
int result = handle.insert(
"INSERT INTO flights(flight_id, departure_airport, arrival_airport, departure_time, arrival_time) " +
"VALUES ('C1671','ORD','DUS','2015-04-01T06:00:00-05:00','2015-04-01T21:00:00+02:00')");
assertThat(result).isGreaterThan(0);
final DateTime departureTime = flightDao.getDepartureTime("C1671");
final DateTime arrivalTime = flightDao.getArrivalTime("C1671");
assertThat(departureTime).isEqualTo(ISO_FMT.parseDateTime("2015-04-01T06:00:00-05:00"));
assertThat(arrivalTime).isEqualTo(ISO_FMT.parseDateTime("2015-04-01T21:00:00+02:00"));
}
public interface FlightDao {
@SqlUpdate("INSERT INTO flights(flight_id, departure_airport, arrival_airport,departure_time, arrival_time) " +
"VALUES (:flight_id, :departure_airport, :arrival_airport, :departure_time, :arrival_time)")
int insert(@Bind("flight_id") String flightId, @Bind("departure_airport") String departureAirport,
@Bind("arrival_airport") String arrivalAirport,
@Bind("departure_time") DateTime departureTime, @Bind("arrival_time") DateTime arrivalTime);
@SqlQuery("SELECT arrival_time FROM flights WHERE flight_id=:flight_id")
DateTime getArrivalTime(@Bind("flight_id") String flightId);
@SqlQuery("SELECT departure_time FROM flights WHERE flight_id=:flight_id")
DateTime getDepartureTime(@Bind("flight_id") String flightId);
}
}