refactor TimeUtility class to make it testable

+ added a test class for TimeUtility


Former-commit-id: 54d9cf2bf8da37bb723dd5defebbfd3057fef214
This commit is contained in:
Daniel Collin 2015-12-14 17:10:14 +01:00
parent 41d704ad73
commit 9802c08270
4 changed files with 228 additions and 115 deletions

View file

@ -67,20 +67,24 @@ public class DataAggregatorDaemon extends TimerTask implements HalDaemon {
PreparedStatement stmt = null; PreparedStatement stmt = null;
try { try {
stmt = db.getPreparedStatement("SELECT MAX(timestamp_end) FROM sensor_data_aggr WHERE sensor_id == ?"); stmt = db.getPreparedStatement("SELECT MAX(timestamp_end) FROM sensor_data_aggr"
+ " WHERE sensor_id == ?"
+ " AND timestamp_end-timestamp_start == ?");
stmt.setLong(1, sensorId); stmt.setLong(1, sensorId);
Long maxDBTimestamp = DBConnection.exec(stmt, new SimpleSQLResult<Long>()); stmt.setLong(2, toPeriodSizeInMs-1);
if(maxDBTimestamp == null) Long maxTimestampFoundForSensor = DBConnection.exec(stmt, new SimpleSQLResult<Long>());
maxDBTimestamp = 0l; if(maxTimestampFoundForSensor == null)
maxTimestampFoundForSensor = 0l;
long minPeriodTimestamp = TimeUtility.getTimestampPeriodStart(toPeriodSizeInMs, System.currentTimeMillis()); long currentPeriodStartTimestamp = TimeUtility.getTimestampPeriodStart(toPeriodSizeInMs, System.currentTimeMillis());
logger.fine("Calculating periods... (from:"+ maxDBTimestamp +", to:"+ minPeriodTimestamp +")"); logger.fine("Calculating periods... (from:"+ maxTimestampFoundForSensor +", to:"+ currentPeriodStartTimestamp +")");
stmt = db.getPreparedStatement("SELECT *, 1 AS confidence, timestamp AS timestamp_start FROM sensor_data_raw" stmt = db.getPreparedStatement("SELECT *, 1 AS confidence, timestamp AS timestamp_start FROM sensor_data_raw"
+" WHERE sensor_id == ? AND ? < timestamp AND timestamp < ? " +" WHERE sensor_id == ?"
+ " AND ? < timestamp"
+ " AND timestamp < ? "
+" ORDER BY timestamp ASC"); +" ORDER BY timestamp ASC");
stmt.setLong(1, sensorId); stmt.setLong(1, sensorId);
stmt.setLong(2, maxDBTimestamp); stmt.setLong(2, maxTimestampFoundForSensor);
stmt.setLong(3, minPeriodTimestamp); stmt.setLong(3, currentPeriodStartTimestamp);
DBConnection.exec(stmt, new DataAggregator(sensorId, toPeriodSizeInMs, expectedSampleCount, aggrMethod)); DBConnection.exec(stmt, new DataAggregator(sensorId, toPeriodSizeInMs, expectedSampleCount, aggrMethod));
} catch (SQLException e) { } catch (SQLException e) {
logger.log(Level.SEVERE, null, e); logger.log(Level.SEVERE, null, e);
@ -99,21 +103,25 @@ public class DataAggregatorDaemon extends TimerTask implements HalDaemon {
try { try {
stmt = db.getPreparedStatement("SELECT MAX(timestamp_end) FROM sensor_data_aggr" stmt = db.getPreparedStatement("SELECT MAX(timestamp_end) FROM sensor_data_aggr"
+" WHERE sensor_id == ? AND timestamp_end-timestamp_start == ?"); +" WHERE sensor_id == ?"
+ " AND timestamp_end-timestamp_start == ?");
stmt.setLong(1, sensorId); stmt.setLong(1, sensorId);
stmt.setLong(2, toPeriodSizeInMs-1); stmt.setLong(2, toPeriodSizeInMs-1);
Long maxDBTimestamp = DBConnection.exec(stmt, new SimpleSQLResult<Long>()); Long maxTimestampFoundForSensor = DBConnection.exec(stmt, new SimpleSQLResult<Long>());
if(maxDBTimestamp == null) if(maxTimestampFoundForSensor == null)
maxDBTimestamp = 0l; maxTimestampFoundForSensor = 0l;
long hourPeriodTimestamp = TimeUtility.getTimestampPeriodStart(toPeriodSizeInMs, System.currentTimeMillis()); long currentPeriodStartTimestamp = TimeUtility.getTimestampPeriodStart(toPeriodSizeInMs, System.currentTimeMillis());
logger.fine("Calculating periods... (from:"+ maxDBTimestamp +", to:"+ hourPeriodTimestamp +")"); logger.fine("Calculating periods... (from:"+ maxTimestampFoundForSensor +", to:"+ currentPeriodStartTimestamp +")");
stmt = db.getPreparedStatement("SELECT * FROM sensor_data_aggr" stmt = db.getPreparedStatement("SELECT * FROM sensor_data_aggr"
+" WHERE sensor_id == ? AND ? < timestamp_start AND timestamp_start < ? AND timestamp_end-timestamp_start == ?" +" WHERE sensor_id == ?"
+ " AND ? < timestamp_start"
+ " AND timestamp_start < ?"
+ " AND timestamp_end-timestamp_start == ?"
+" ORDER BY timestamp_start ASC"); +" ORDER BY timestamp_start ASC");
stmt.setLong(1, sensorId); stmt.setLong(1, sensorId);
stmt.setLong(2, maxDBTimestamp); stmt.setLong(2, maxTimestampFoundForSensor);
stmt.setLong(3, hourPeriodTimestamp); stmt.setLong(3, currentPeriodStartTimestamp);
stmt.setLong(4, fromPeriodSizeInMs-1); stmt.setLong(4, fromPeriodSizeInMs-1);
DBConnection.exec(stmt, new DataAggregator(sensorId, toPeriodSizeInMs, expectedSampleCount, aggrMethod)); DBConnection.exec(stmt, new DataAggregator(sensorId, toPeriodSizeInMs, expectedSampleCount, aggrMethod));
} catch (SQLException e) { } catch (SQLException e) {
@ -166,7 +174,7 @@ public class DataAggregatorDaemon extends TimerTask implements HalDaemon {
preparedInsertStmt.setLong(2, ++highestSequenceId); preparedInsertStmt.setLong(2, ++highestSequenceId);
preparedInsertStmt.setLong(3, currentPeriodTimestamp); preparedInsertStmt.setLong(3, currentPeriodTimestamp);
preparedInsertStmt.setLong(4, currentPeriodTimestamp + this.aggrTimeInMs - 1); preparedInsertStmt.setLong(4, currentPeriodTimestamp + this.aggrTimeInMs - 1);
preparedInsertStmt.setInt(5, (int)data); //TODO: make data float in DB preparedInsertStmt.setInt(5, (int)data); //TODO: make data float in DB to handle aggrMethod.AVG where the data must be able to be saved as a float
preparedInsertStmt.setFloat(6, aggrConfidence); preparedInsertStmt.setFloat(6, aggrConfidence);
preparedInsertStmt.addBatch(); preparedInsertStmt.addBatch();

View file

@ -30,7 +30,7 @@ public class DataDeletionDaemon extends TimerTask implements HalDaemon {
List<Sensor> sensorList = Sensor.getSensors(HalContext.getDB()); List<Sensor> sensorList = Sensor.getSensors(HalContext.getDB());
for(Sensor sensor : sensorList){ for(Sensor sensor : sensorList){
logger.fine("Deleting old data for sensor id: " + sensor.getId()); logger.fine("Deleting old data for sensor id: " + sensor.getId());
cleanupSensor(sensor.getId()); cleanupSensor(sensor);
} }
logger.fine("Data cleanup done"); logger.fine("Data cleanup done");
} catch (SQLException e) { } catch (SQLException e) {
@ -38,7 +38,30 @@ public class DataDeletionDaemon extends TimerTask implements HalDaemon {
} }
} }
public void cleanupSensor(long sensorId) { public void cleanupSensor(Sensor sensor) {
logger.fine("The sensor is of type: " + sensor.getType());
if(sensor.getType().equals("PowerMeter")){
//if(sensor.isInternal()){ //TODO
cleanupInternalSensorData(sensor.getId(), TimeUtility.HOUR_IN_MS, TimeUtility.FIVE_MINUTES_IN_MS, TimeUtility.DAY_IN_MS);
cleanupInternalSensorData(sensor.getId(), TimeUtility.DAY_IN_MS, TimeUtility.HOUR_IN_MS, TimeUtility.WEEK_IN_MS);
//}else{ //TODO
//cleanupExternalSensorData(sensor.getId(), TimeUtility.FIVE_MINUTES_IN_MS, TimeUtility.DAY_IN_MS);
//cleanupExternalSensorData(sensor.getId(), TimeUtility.DAY_IN_MS, TimeUtility.WEEK_IN_MS);
//}
clearPeriodsOfWrongLenght(sensor.getId(), TimeUtility.FIVE_MINUTES_IN_MS, TimeUtility.HOUR_IN_MS, TimeUtility.WEEK_IN_MS);
}else{
logger.fine("The sensor type is not supported by the cleanup deamon. Ignoring");
}
}
/**
* Will clear periods only if it has been aggregated and are too old.
* @param sensorId
* @Param referencePeriodlength Will only clear periods older than the newest period of this length.
* @Param clearPeriodlength Will clear periods with this length
* @param olderThan Data must be older than this many ms to be cleared from the DB
*/
private void cleanupInternalSensorData(long sensorId, long referencePeriodlength, long clearPeriodlength, long olderThan){
DBConnection db = HalContext.getDB(); DBConnection db = HalContext.getDB();
PreparedStatement stmt = null; PreparedStatement stmt = null;
try { try {
@ -48,7 +71,7 @@ public class DataDeletionDaemon extends TimerTask implements HalDaemon {
stmt = db.getPreparedStatement("SELECT MAX(timestamp_end) FROM sensor_data_aggr" stmt = db.getPreparedStatement("SELECT MAX(timestamp_end) FROM sensor_data_aggr"
+" WHERE sensor_id == ? AND timestamp_end-timestamp_start == ?"); +" WHERE sensor_id == ? AND timestamp_end-timestamp_start == ?");
stmt.setLong(1, sensorId); stmt.setLong(1, sensorId);
stmt.setLong(2, TimeUtility.HOUR_IN_MS-1); stmt.setLong(2, referencePeriodlength-1);
maxDBTimestamp = DBConnection.exec(stmt, new SimpleSQLResult<Long>()); maxDBTimestamp = DBConnection.exec(stmt, new SimpleSQLResult<Long>());
if(maxDBTimestamp == null) if(maxDBTimestamp == null)
maxDBTimestamp = 0l; maxDBTimestamp = 0l;
@ -60,35 +83,65 @@ public class DataDeletionDaemon extends TimerTask implements HalDaemon {
+ "AND timestamp_end < ?"); + "AND timestamp_end < ?");
stmt.setLong(1, sensorId); stmt.setLong(1, sensorId);
stmt.setLong(2, maxDBTimestamp); stmt.setLong(2, maxDBTimestamp);
stmt.setLong(3, TimeUtility.FIVE_MINUTES_IN_MS-1); stmt.setLong(3, clearPeriodlength-1);
stmt.setLong(4, System.currentTimeMillis()-TimeUtility.DAY_IN_MS); stmt.setLong(4, System.currentTimeMillis()-olderThan);
DBConnection.exec(stmt, new AggregateDataDeleter(sensorId));
// delete too old 1 hour periods that already have been aggregated into days
stmt = db.getPreparedStatement("SELECT MAX(timestamp_end) FROM sensor_data_aggr"
+" WHERE sensor_id == ? AND timestamp_end-timestamp_start == ?");
stmt.setLong(1, sensorId);
stmt.setLong(2, TimeUtility.DAY_IN_MS-1);
maxDBTimestamp = DBConnection.exec(stmt, new SimpleSQLResult<Long>());
if(maxDBTimestamp == null)
maxDBTimestamp = 0l;
stmt = db.getPreparedStatement("SELECT * FROM sensor_data_aggr"
+" WHERE sensor_id == ? "
+ "AND timestamp_end < ? "
+ "AND timestamp_end-timestamp_start == ?"
+ "AND timestamp_end < ?");
stmt.setLong(1, sensorId);
stmt.setLong(2, maxDBTimestamp);
stmt.setLong(3, TimeUtility.HOUR_IN_MS-1);
stmt.setLong(4, System.currentTimeMillis()-TimeUtility.WEEK_IN_MS);
DBConnection.exec(stmt, new AggregateDataDeleter(sensorId)); DBConnection.exec(stmt, new AggregateDataDeleter(sensorId));
} catch (SQLException e) { } catch (SQLException e) {
logger.log(Level.SEVERE, null, e); logger.log(Level.SEVERE, null, e);
} }
} }
private class AggregateDataDeleter implements SQLResultHandler<Object>{ /**
* Will clear periods if they are too old.
* @param sensorId
* @Param clearPeriodlength Will clear periods with this length
* @param olderThan Data must be older than this many ms to be cleared from the DB
*/
private void cleanupExternalSensorData(long sensorId, long clearPeriodlength, long olderThan){
DBConnection db = HalContext.getDB();
PreparedStatement stmt = null;
try {
stmt = db.getPreparedStatement("SELECT * FROM sensor_data_aggr"
+" WHERE sensor_id == ? "
+ "AND timestamp_end-timestamp_start == ?"
+ "AND timestamp_end < ?");
stmt.setLong(1, sensorId);
stmt.setLong(2, clearPeriodlength-1);
stmt.setLong(3, System.currentTimeMillis()-olderThan);
DBConnection.exec(stmt, new AggregateDataDeleter(sensorId));
} catch (SQLException e) {
logger.log(Level.SEVERE, null, e);
}
}
/**
* Will delete all aggregated entries for a sensor id where the period length is not expected
* @param sensorId
* @param expectedPeriodLengths
*/
private void clearPeriodsOfWrongLenght(long sensorId, long... expectedPeriodLengths){
DBConnection db = HalContext.getDB();
PreparedStatement stmt = null;
try {
StringBuilder querry = new StringBuilder("SELECT * FROM sensor_data_aggr WHERE sensor_id == ?");
for(int i = 0; i < expectedPeriodLengths.length; ++i){
querry.append(" AND timestamp_end-timestamp_start != ?");
}
stmt = db.getPreparedStatement(querry.toString());
for(int i = 0; i < expectedPeriodLengths.length; ++i){
stmt.setLong(i+1, expectedPeriodLengths[i]);
}
long deletedRows = DBConnection.exec(stmt, new AggregateDataDeleter(sensorId));
if(deletedRows > 0){
logger.severe("removed aggregated data with an unknown period length. Is the database corrupt?");
}
} catch (SQLException e) {
logger.log(Level.SEVERE, null, e);
}
}
private class AggregateDataDeleter implements SQLResultHandler<Long>{
private long sensorId = -1; private long sensorId = -1;
public AggregateDataDeleter(long sensorId){ public AggregateDataDeleter(long sensorId){
@ -96,7 +149,8 @@ public class DataDeletionDaemon extends TimerTask implements HalDaemon {
} }
@Override @Override
public Object handleQueryResult(Statement stmt, ResultSet result) throws SQLException { public Long handleQueryResult(Statement stmt, ResultSet result) throws SQLException {
long count = 0;
try{ try{
HalContext.getDB().getConnection().setAutoCommit(false); HalContext.getDB().getConnection().setAutoCommit(false);
PreparedStatement preparedDeleteStmt = HalContext.getDB().getPreparedStatement("DELETE FROM sensor_data_aggr WHERE sensor_id == ? AND sequence_id == ?"); PreparedStatement preparedDeleteStmt = HalContext.getDB().getPreparedStatement("DELETE FROM sensor_data_aggr WHERE sensor_id == ? AND sequence_id == ?");
@ -104,20 +158,22 @@ public class DataDeletionDaemon extends TimerTask implements HalDaemon {
if(sensorId != result.getInt("sensor_id")){ if(sensorId != result.getInt("sensor_id")){
throw new IllegalArgumentException("Found entry for aggregation for the wrong sensorId (expecting: "+sensorId+", but was: "+result.getInt("sensor_id")+")"); throw new IllegalArgumentException("Found entry for aggregation for the wrong sensorId (expecting: "+sensorId+", but was: "+result.getInt("sensor_id")+")");
} }
logger.finer("Deleting sensor aggregate entry timestamp: "+ result.getLong("timestamp_start") +" - "+ result.getLong("timestamp_end")); logger.finer("Deleting sensor aggregate entry timestamp: "+ result.getLong("timestamp_start") +" - "+ result.getLong("timestamp_end") + " (" + TimeUtility.msToString(result.getLong("timestamp_end")-result.getLong("timestamp_start")) + ")");
preparedDeleteStmt.setInt(1, result.getInt("sensor_id")); preparedDeleteStmt.setInt(1, result.getInt("sensor_id"));
preparedDeleteStmt.setLong(2, result.getLong("sequence_id")); preparedDeleteStmt.setLong(2, result.getLong("sequence_id"));
preparedDeleteStmt.addBatch(); preparedDeleteStmt.addBatch();
count++;
} }
DBConnection.execBatch(preparedDeleteStmt); DBConnection.execBatch(preparedDeleteStmt);
HalContext.getDB().getConnection().commit(); HalContext.getDB().getConnection().commit();
}catch(Exception e){ }catch(Exception e){
HalContext.getDB().getConnection().rollback(); HalContext.getDB().getConnection().rollback();
throw e;
}finally{ }finally{
HalContext.getDB().getConnection().setAutoCommit(true); HalContext.getDB().getConnection().setAutoCommit(true);
} }
return null; return count;
} }
} }

View file

@ -10,68 +10,93 @@ public class TimeUtility {
public static final long DAY_IN_MS = HOUR_IN_MS * 24; public static final long DAY_IN_MS = HOUR_IN_MS * 24;
public static final long WEEK_IN_MS = DAY_IN_MS * 7; public static final long WEEK_IN_MS = DAY_IN_MS * 7;
/**
* Get the timstamp for the given timestamp floored with the period length. The result should point to the beginning of the timestamps period.
* @param periodLengthInMs The periods length to floor the timestamp with
* @param timestamp The timestamp to floor.
* @return
*/
public static long getTimestampPeriodStart(long periodLengthInMs, long timestamp){ public static long getTimestampPeriodStart(long periodLengthInMs, long timestamp){
if(periodLengthInMs < DAY_IN_MS){ if(periodLengthInMs < DAY_IN_MS){ //simple math if the period is less than a day long
long tmp = timestamp % periodLengthInMs; return timestamp - (timestamp % periodLengthInMs);
return timestamp - tmp;
}else{ }else{
long tmp = periodLengthInMs; Calendar cal = Calendar.getInstance();
int milliseconds = (int) (tmp % SECOND_IN_MS); cal.setTimeInMillis(timestamp);
tmp -= milliseconds * SECOND_IN_MS; boolean clear = false;
int seconds = (int) ((tmp % MINUTES_IN_MS) / SECOND_IN_MS); int days = millisecondsToDays(periodLengthInMs);
tmp -= seconds * MINUTES_IN_MS; if(days > 0){
int minutes = (int) ((tmp % HOUR_IN_MS) / MINUTES_IN_MS); int currentDay = cal.get(Calendar.DAY_OF_YEAR);
tmp -= minutes * HOUR_IN_MS; cal.set(Calendar.DAY_OF_YEAR, (currentDay/days)*days);
int hours = (int) ((tmp % DAY_IN_MS) / HOUR_IN_MS); clear = true;
tmp -= hours * DAY_IN_MS; }
int days = (int) (tmp / DAY_IN_MS); int hours = millisecondsToHourOfDay(periodLengthInMs);
return getTimestampPeriodStart(days, hours, minutes, seconds, milliseconds, timestamp); if(hours > 0){
int currentHour = cal.get(Calendar.HOUR_OF_DAY);
cal.set(Calendar.HOUR_OF_DAY, (currentHour/hours)*hours);
clear = true;
}else if(clear){
cal.set(Calendar.HOUR_OF_DAY, 0);
}
int minutes = millisecondsToMinuteOfHour(periodLengthInMs);
if(minutes > 0){
int currentMinute = cal.get(Calendar.MINUTE);
cal.set(Calendar.MINUTE, (currentMinute/minutes)*minutes);
clear = true;
}else if(clear){
cal.set(Calendar.MINUTE, 0);
}
int seconds = millisecondsToSecondOfMinute(periodLengthInMs);
if(seconds > 0){
int currentSecond = cal.get(Calendar.SECOND);
cal.set(Calendar.SECOND, (currentSecond/seconds)*seconds);
clear = true;
}else if(clear){
cal.set(Calendar.SECOND, 0);
}
int milliseconds = millisecondsToMillisecondInSecond(periodLengthInMs);
if(milliseconds > 0){
int currentMillisecond = cal.get(Calendar.MILLISECOND);
cal.set(Calendar.MILLISECOND, (currentMillisecond/milliseconds)*milliseconds);
}else if(clear){
cal.set(Calendar.MILLISECOND, 0);
}
return cal.getTimeInMillis();
} }
} }
private static long getTimestampPeriodStart(int days, int hours, int minutes, int seconds, int milliseconds, long timestamp) { public static int millisecondsToMillisecondInSecond(long ms){
Calendar cal = Calendar.getInstance(); return (int) (ms % SECOND_IN_MS);
cal.setTimeInMillis(timestamp); }
boolean clear = false;
public static int millisecondsToSecondOfMinute(long ms){
if(days > 0){ return (int) ((ms % MINUTES_IN_MS) / SECOND_IN_MS);
int currentDay = cal.get(Calendar.DAY_OF_YEAR); }
cal.set(Calendar.DAY_OF_YEAR, (currentDay/days)*days);
clear = true; public static int millisecondsToMinuteOfHour(long ms){
} return (int) ((ms % HOUR_IN_MS) / MINUTES_IN_MS);
}
if(hours > 0){
int currentHour = cal.get(Calendar.HOUR_OF_DAY); public static int millisecondsToHourOfDay(long ms){
cal.set(Calendar.HOUR_OF_DAY, (currentHour/hours)*hours); return (int) ((ms % DAY_IN_MS) / HOUR_IN_MS);
clear = true; }
}else if(clear){
cal.set(Calendar.HOUR_OF_DAY, 0); public static int millisecondsToDays(long ms){
} return (int) (ms / DAY_IN_MS);
}
if(minutes > 0){
int currentMinute = cal.get(Calendar.MINUTE); public static String msToString(long ms){
cal.set(Calendar.MINUTE, (currentMinute/minutes)*minutes); String retval = "";
clear = true; int days = millisecondsToDays(ms);
}else if(clear){ retval += days + "days+";
cal.set(Calendar.MINUTE, 0); int hours = millisecondsToHourOfDay(ms);
} retval += (hours<10?"0"+hours:hours);
int minutes = millisecondsToMinuteOfHour(ms);
if(seconds > 0){ retval += ":" + (minutes<10?"0"+minutes:minutes);
int currentSecond = cal.get(Calendar.SECOND); int seconds = millisecondsToSecondOfMinute(ms);
cal.set(Calendar.SECOND, (currentSecond/seconds)*seconds); retval += ":" + (seconds<10?"0"+seconds:seconds);
clear = true; int milliseconds = millisecondsToMillisecondInSecond(ms);
}else if(clear){ retval += "." + (milliseconds<100?"0"+(milliseconds<10?"0"+milliseconds:milliseconds):milliseconds);
cal.set(Calendar.SECOND, 0); return retval;
}
if(milliseconds > 0){
int currentMillisecond = cal.get(Calendar.MILLISECOND);
cal.set(Calendar.MILLISECOND, (currentMillisecond/milliseconds)*milliseconds);
}else if(clear){
cal.set(Calendar.MILLISECOND, 0);
}
return cal.getTimeInMillis();
} }
} }

View file

@ -20,9 +20,9 @@ public class TimeUtilityTest {
@Test @Test
public void testDayStartForCurrentTime(){ public void testDayStartForCurrentTime(){
long thisDayStartedAt = TimeUtility.getTimestampPeriodStart(TimeUtility.DAY_IN_MS, currentTime); long thisPeriodStartedAt = TimeUtility.getTimestampPeriodStart(TimeUtility.DAY_IN_MS, currentTime);
Calendar testCalendar = Calendar.getInstance(); Calendar testCalendar = Calendar.getInstance();
testCalendar.setTimeInMillis(thisDayStartedAt); testCalendar.setTimeInMillis(thisPeriodStartedAt);
assertEquals("millisecond is wrong", 0, testCalendar.get(Calendar.MILLISECOND)); assertEquals("millisecond is wrong", 0, testCalendar.get(Calendar.MILLISECOND));
assertEquals("second is wrong", 0, testCalendar.get(Calendar.SECOND)); assertEquals("second is wrong", 0, testCalendar.get(Calendar.SECOND));
@ -33,9 +33,9 @@ public class TimeUtilityTest {
@Test @Test
public void testHourStartForCurrentTime(){ public void testHourStartForCurrentTime(){
long thisDayStartedAt = TimeUtility.getTimestampPeriodStart(TimeUtility.HOUR_IN_MS, currentTime); long thisPeriodStartedAt = TimeUtility.getTimestampPeriodStart(TimeUtility.HOUR_IN_MS, currentTime);
Calendar testCalendar = Calendar.getInstance(); Calendar testCalendar = Calendar.getInstance();
testCalendar.setTimeInMillis(thisDayStartedAt); testCalendar.setTimeInMillis(thisPeriodStartedAt);
assertEquals("millisecond is wrong", 0, testCalendar.get(Calendar.MILLISECOND)); assertEquals("millisecond is wrong", 0, testCalendar.get(Calendar.MILLISECOND));
assertEquals("second is wrong", 0, testCalendar.get(Calendar.SECOND)); assertEquals("second is wrong", 0, testCalendar.get(Calendar.SECOND));
@ -46,9 +46,9 @@ public class TimeUtilityTest {
@Test @Test
public void testMinuteStartForCurrentTime(){ public void testMinuteStartForCurrentTime(){
long thisDayStartedAt = TimeUtility.getTimestampPeriodStart(TimeUtility.MINUTES_IN_MS, currentTime); long thisPeriodStartedAt = TimeUtility.getTimestampPeriodStart(TimeUtility.MINUTES_IN_MS, currentTime);
Calendar testCalendar = Calendar.getInstance(); Calendar testCalendar = Calendar.getInstance();
testCalendar.setTimeInMillis(thisDayStartedAt); testCalendar.setTimeInMillis(thisPeriodStartedAt);
assertEquals("millisecond is wrong", 0, testCalendar.get(Calendar.MILLISECOND)); assertEquals("millisecond is wrong", 0, testCalendar.get(Calendar.MILLISECOND));
assertEquals("second is wrong", 0, testCalendar.get(Calendar.SECOND)); assertEquals("second is wrong", 0, testCalendar.get(Calendar.SECOND));
@ -59,9 +59,9 @@ public class TimeUtilityTest {
@Test @Test
public void testSecondStartForCurrentTime(){ public void testSecondStartForCurrentTime(){
long thisDayStartedAt = TimeUtility.getTimestampPeriodStart(TimeUtility.SECOND_IN_MS, currentTime); long thisPeriodStartedAt = TimeUtility.getTimestampPeriodStart(TimeUtility.SECOND_IN_MS, currentTime);
Calendar testCalendar = Calendar.getInstance(); Calendar testCalendar = Calendar.getInstance();
testCalendar.setTimeInMillis(thisDayStartedAt); testCalendar.setTimeInMillis(thisPeriodStartedAt);
assertEquals("millisecond is wrong", 0, testCalendar.get(Calendar.MILLISECOND)); assertEquals("millisecond is wrong", 0, testCalendar.get(Calendar.MILLISECOND));
assertEquals("second is wrong", referenceCalendar.get(Calendar.SECOND), testCalendar.get(Calendar.SECOND)); assertEquals("second is wrong", referenceCalendar.get(Calendar.SECOND), testCalendar.get(Calendar.SECOND));
@ -70,4 +70,28 @@ public class TimeUtilityTest {
assertEquals("day is wrong", referenceCalendar.get(Calendar.DAY_OF_YEAR), testCalendar.get(Calendar.DAY_OF_YEAR)); assertEquals("day is wrong", referenceCalendar.get(Calendar.DAY_OF_YEAR), testCalendar.get(Calendar.DAY_OF_YEAR));
} }
@Test
public void testMsToString(){
//low values
assertEquals("0days+00:00:00.000", TimeUtility.msToString(0));
assertEquals("0days+00:00:00.001", TimeUtility.msToString(1));
assertEquals("0days+00:00:01.000", TimeUtility.msToString(TimeUtility.SECOND_IN_MS));
assertEquals("0days+00:01:00.000", TimeUtility.msToString(TimeUtility.MINUTES_IN_MS));
assertEquals("0days+00:05:00.000", TimeUtility.msToString(TimeUtility.FIVE_MINUTES_IN_MS));
assertEquals("0days+01:00:00.000", TimeUtility.msToString(TimeUtility.HOUR_IN_MS));
assertEquals("1days+00:00:00.000", TimeUtility.msToString(TimeUtility.DAY_IN_MS));
assertEquals("7days+00:00:00.000", TimeUtility.msToString(TimeUtility.WEEK_IN_MS));
//high values
assertEquals("0days+00:00:00.999", TimeUtility.msToString(999));
assertEquals("0days+00:00:59.000", TimeUtility.msToString(TimeUtility.SECOND_IN_MS*59));
assertEquals("0days+00:59:00.000", TimeUtility.msToString(TimeUtility.MINUTES_IN_MS*59));
assertEquals("0days+23:00:00.000", TimeUtility.msToString(TimeUtility.HOUR_IN_MS*23));
assertEquals("369days+00:00:00.000", TimeUtility.msToString(TimeUtility.DAY_IN_MS*369));
//combinations
long ms = (TimeUtility.DAY_IN_MS*999) + (TimeUtility.HOUR_IN_MS*23) + (TimeUtility.MINUTES_IN_MS*59) + (TimeUtility.SECOND_IN_MS*59) + 999;
assertEquals("999days+23:59:59.999", TimeUtility.msToString(ms));
}
} }