/*******************************************************************************
 * Copyright (c) 2011 The OpenNMS Group, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *******************************************************************************/

package org.jrobin.core.timespec;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.jrobin.core.RrdException;
import org.junit.Before;
import org.junit.Test;

/**
 * Mostly about testing TimeParser; relies on TimeSpec to be working as well (and to some degree exercises it implicitly; 
 * if you break TimeSpec, these tests may fail when doing relative times (e.g start = X, end = start+100 and the like)
 *  
 * NB: if you're adding tests here, you may wish to consider replicating them in RrdGraphControllerTest in OpenNMS as well
 * Or not.  As you see fit :)
 * 
 * @author cmiskell
 *
 */
public class TimeParserTest {
	
	private final static int ONE_HOUR_IN_MILLIS=60*60*1000;
	private final static int ONE_DAY_IN_MILLIS=24 * ONE_HOUR_IN_MILLIS;
	//private final static int ONE_NIGHT_IN_PARIS = 0x7a57e1e55;

	
	@Before
	public void setup() throws InterruptedException {
		//Yeah, this looks weird, but there's method to my madness.  
		// Many of these tests create Calendars based on the current time, then use the 
		// parsing code which will assume something about when 'now' is, often the current day/week
		// If we're running around midnight and the Calendar gets created on one day and the parsing
		// happens on the next, you'll get spurious failures, which would be really annoying and hard
		// to replicate.  Initial tests show that most tests take ~100ms, so if it's within 10 seconds
		// of midnight, wait for 30 seconds (and print a message saing why)
		Calendar now = new GregorianCalendar();
		if(now.get(Calendar.HOUR_OF_DAY) == 23 && now.get(Calendar.MINUTE) > 59 && now.get(Calendar.SECOND) > 50) {
			Thread.sleep(30000);
		}
	}
	
	private long[] parseTimes(String startTime, String endTime) {
	   	TimeParser startParser = new TimeParser(startTime);
    	TimeParser endParser = new TimeParser(endTime);
        try {

        	TimeSpec specStart = startParser.parse();
        	TimeSpec specEnd = endParser.parse();
        	return TimeSpec.getTimestamps(specStart, specEnd);
		} catch (RrdException e) {
			throw new IllegalArgumentException("Could not parse start '"+ startTime+"' and end '"+endTime+"' as valid time specifications", e);
		}

	}
	
	/**
	 * Set all fields smaller than an hour to 0.
	 * @param now
	 */
	private void setSubHourFieldsZero(Calendar cal) {
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
	}

	/**
	 * Set all fields smaller than a day to 0 (rounding down to midnight effectively)
	 * @param now
	 */
	private void setSubDayFieldsZero(Calendar cal) {
		setSubHourFieldsZero(cal);
		cal.set(Calendar.HOUR_OF_DAY,0);
	}

	/**
	 * Kinda like the JUnit asserts for doubles, which allows an "epsilon"
	 * But this is for integers, and with a specific description in the assert
	 * just for timestamps.
	 * 
	 * All times are expected in milliseconds
	 * 
	 * @param expected - expected value
	 * @param actual - actual value
	 * @param epsilon - the maximum difference
	 * @param desc - some description of the time.  Usually "start" or "end", could be others
	 */
	private void assertTimestampsEqualWithEpsilon(long expected, long actual, int epsilon, String desc) {
		assertTrue("Expected a "+desc+" time within "+epsilon+"ms of "+ expected
				+ " but got " + actual,
				Math.abs(actual - expected) < epsilon);
	}
	
	/**
	 * Test the specification of just an "hour" (assumed today) for
	 * both start and end, using the 24hour clock
	 */
	@Test
	public void test24HourClockHourTodayStartEndTime() {
		Calendar now = new GregorianCalendar();
		now.set(Calendar.HOUR_OF_DAY, 8); //8am
		setSubHourFieldsZero(now);
		
		Date startDate = now.getTime();
		now.set(Calendar.HOUR_OF_DAY, 16); //4pm
		setSubHourFieldsZero(now);
		Date endDate = now.getTime();
		
		long[] result = this.parseTimes("08", "16");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);

	}
	
	/**
	 * Test the specification of just an "hour" (assumed today) start using "midnight", end = now
	 */
	@Test
	public void testMidnightToday() {
		Calendar now = new GregorianCalendar();
		now.set(Calendar.HOUR_OF_DAY, 0); //midnight
		setSubHourFieldsZero(now);
		
		Date startDate = now.getTime();
		
		long[] result = this.parseTimes("midnight", "16");
		long start = result[0] * 1000;

		assertEquals(startDate.getTime(), start);

	}

	/**
	 * Test the specification of just an "hour" (assumed today) start using "noon", end = now
	 */
	@Test
	public void testNoonToday() {
		Calendar now = new GregorianCalendar();
		now.set(Calendar.HOUR_OF_DAY, 12); //noon
		setSubHourFieldsZero(now);
		
		Date startDate = now.getTime();
		
		long[] result = this.parseTimes("noon", "16");
		long start = result[0] * 1000;

		assertEquals(startDate.getTime(), start);

	}

	/**
	 * Test the specification of just an "hour" (assumed today) for
	 * both start and end, using am/pm designators
	 */
	@Test
	public void testAMPMClockHourTodayStartEndTime() {
		Calendar now = new GregorianCalendar();
		now.set(Calendar.HOUR_OF_DAY, 8); //8am
		setSubHourFieldsZero(now);
		Date startDate = now.getTime();
		now.set(Calendar.HOUR_OF_DAY, 16); //4pm
		setSubHourFieldsZero(now);
		Date endDate = now.getTime();
		
		long[] result = this.parseTimes("8am", "4pm");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);

	}

	/**
	 * Test that we can explicitly use the term "today", e.g. "today 9am"
	 * NB: This was failing in 1.5.12, so well worth testing :)
	 */
	@Test
	public void testTodayTime() {
		Calendar now = new GregorianCalendar();
		now.set(Calendar.HOUR_OF_DAY, 9); //9am
		setSubHourFieldsZero(now);
		Date startDate = now.getTime();
		now.set(Calendar.HOUR_OF_DAY, 17); //5pm
		setSubHourFieldsZero(now);
		Date endDate = now.getTime();
		
		long[] result = this.parseTimes("9am today", "5pm today");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);
	}

	/**
	 * Test that we can explicitly use the term "yesterday", e.g. "yesterday 9am"
	 * NB: This was failing in 1.5.12, so well worth testing :)
	 */
	@Test
	public void testYesterdayTime() {
		Calendar now = new GregorianCalendar();
		now.set(Calendar.HOUR_OF_DAY, 9); //9am
		setSubHourFieldsZero(now);
		Date startDate = new Date(now.getTimeInMillis()-ONE_DAY_IN_MILLIS);
		now.set(Calendar.HOUR_OF_DAY, 17); //5pm
		setSubHourFieldsZero(now);
		Date endDate = new Date(now.getTimeInMillis()-ONE_DAY_IN_MILLIS);
		
		long[] result = this.parseTimes("9am yesterday", "5pm yesterday");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);
	}

	/**
	 * Test that we can explicitly use the term "tomorrow", e.g. "tomorrow 9am"
	 * NB: This was failing in 1.5.12, so well worth testing :)
	 */
	@Test
	public void testTomorrowTime() {
		Calendar now = new GregorianCalendar();
		now.set(Calendar.HOUR_OF_DAY, 9); //9am
		setSubHourFieldsZero(now);
		Date startDate = new Date(now.getTimeInMillis()+ONE_DAY_IN_MILLIS);
		now.set(Calendar.HOUR_OF_DAY, 17); //5pm
		setSubHourFieldsZero(now);
		Date endDate = new Date(now.getTimeInMillis()+ONE_DAY_IN_MILLIS);
		
		long[] result = this.parseTimes("9am tomorrow", "5pm tomorrow");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);
	}

	/**
	 * Tests a simple negative hour offset
	 * 
	 * Test the simple start=-1h example from rrdfetch man page.  
	 * End is "now" (implied if missing in most user interfaces), 
	 * start should be 1 hour prior to now 
	 */
	@Test
	public void testSimpleNegativeOffset() {
		Calendar now = new GregorianCalendar();
		Date endDate = now.getTime();
		Date startDate = new Date(now.getTimeInMillis()-ONE_HOUR_IN_MILLIS);
		
		long[] result = this.parseTimes("-1h", "now");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertTimestampsEqualWithEpsilon(endDate.getTime(), end, 1000, "end");
		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");

	}
	
	/**
	 * Test a start relative to an end that isn't now
	 */
	@Test
	public void testRelativeStartOffsetEnd() {
		Calendar now = new GregorianCalendar();
		Date endDate = new Date(now.getTimeInMillis()-ONE_HOUR_IN_MILLIS);
		Date startDate = new Date(now.getTimeInMillis()-(3*ONE_HOUR_IN_MILLIS));

		//End is 1 hour ago; start is 2 hours before that
		long[] result = this.parseTimes("end-2h", "-1h");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertTimestampsEqualWithEpsilon(endDate.getTime(), end, 1000, "end");
		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");

	}

	/**
	 * Test a start relative to an end that isn't now
	 */
	@Test
	public void testRelativeStartOffsetEndAbbreviatedEnd() {
		Calendar now = new GregorianCalendar();
		Date endDate = new Date(now.getTimeInMillis()-ONE_HOUR_IN_MILLIS);
		Date startDate = new Date(now.getTimeInMillis()-(3*ONE_HOUR_IN_MILLIS));

		//End is 1 hour ago; start is 2 hours before that
		long[] result = this.parseTimes("e-2h", "-1h");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertTimestampsEqualWithEpsilon(endDate.getTime(), end, 1000, "end");
		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");

	}

	/**
	 * Test an end relative to a start that isn't now
	 */
	@Test
	public void testRelativeEndOffsetStart() {
		Calendar now = new GregorianCalendar();
		Date endDate = new Date(now.getTimeInMillis()-(2*ONE_HOUR_IN_MILLIS));
		Date startDate = new Date(now.getTimeInMillis()-(4*ONE_HOUR_IN_MILLIS));

		long[] result = this.parseTimes("-4h", "start+2h");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertTimestampsEqualWithEpsilon(endDate.getTime(), end, 1000, "end");
		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");

	}

	/**
	 * Test an end relative to a start that isn't now - abbreviated start (s)
	 */
	@Test
	public void testRelativeEndOffsetStartAbbreviatedStart() {
		Calendar now = new GregorianCalendar();
		Date endDate = new Date(now.getTimeInMillis()-(2*ONE_HOUR_IN_MILLIS));
		Date startDate = new Date(now.getTimeInMillis()-(4*ONE_HOUR_IN_MILLIS));

		long[] result = this.parseTimes("-4h", "s+2h");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertTimestampsEqualWithEpsilon(endDate.getTime(), end, 1000, "end");
		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");

	}

	/**
	 * Test hour:min, and hour.min syntaxes
	 */
	@Test
	public void testHourMinuteSyntax() {
		Calendar now = new GregorianCalendar();
		setSubHourFieldsZero(now);
		now.set(Calendar.HOUR_OF_DAY, 8); 
		now.set(Calendar.MINUTE, 30);
		
		Date startDate = now.getTime();
		now.set(Calendar.HOUR_OF_DAY, 16); 
		now.set(Calendar.MINUTE, 45);
		Date endDate = now.getTime();
		
		//Mixed syntaxes FTW; two tests in one
		//This also exercises the test of the order of parsing (time then day).  If
		// that order is wrong, 8.30 could be (and was at one point) interpreted as a day.month 
		long[] result = this.parseTimes("8.30", "16:45");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);

	}
	
	/**
	 * Test a plain date specified as DD.MM.YYYY
	 */
	@Test
	public void testDateWithDots() {
		//Remember: 0-based month
		Calendar cal = new GregorianCalendar(1980,0,1);
		Date startDate = cal.getTime();
		
		cal = new GregorianCalendar(1980,11,15);
		Date endDate = cal.getTime();
		
		//Start is a simple one; end ensures we have our days/months around the right way.
		long[] result = this.parseTimes("00:00 01.01.1980", "00:00 15.12.1980");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);

	}

	/**
	 * Test a plain date specified as DD/MM/YYYY
	 */
	@Test
	public void testDateWithSlashes() {
		//Remember: 0-based month
		Calendar cal = new GregorianCalendar(1980,0,1);
		Date startDate = cal.getTime();
		
		cal = new GregorianCalendar(1980,11,15);
		Date endDate = cal.getTime();
		
		//Start is a simple one; end ensures we have our days/months around the right way.
		long[] result = this.parseTimes("00:00 01/01/1980", "00:00 12/15/1980");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);

	}
	
	/**
	 * Test a plain date specified as YYYYMMDD
	 */
	@Test
	public void testDateWithNoDelimiters() {
		//Remember: 0-based month
		Calendar cal = new GregorianCalendar(1980,0,1);
		Date startDate = cal.getTime();
		
		cal = new GregorianCalendar(1980,11,15);
		Date endDate = cal.getTime();
		
		//Start is a simple one; end ensures we have our days/months around the right way.
		long[] result = this.parseTimes("00:00 19800101", "00:00 19801215");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);

	}
	
	/**
	 * Test named month dates with no year
	 * 
	 * NB: Seems silly to test all, just test that an arbitrary one works, in both short and long form  
	 * 
	 * If we find actual problems with specific months, we can add more tests
	 */
	@Test
	public void testNamedMonthsNoYear() {
		//Remember: 0-based month -- 2 = March
		Calendar cal = new GregorianCalendar();
		cal.set(Calendar.MONTH, 2); 
		cal.set(Calendar.DAY_OF_MONTH, 1);
		this.setSubDayFieldsZero(cal);
		Date startDate = cal.getTime();
		
		//10 = November 
		cal = new GregorianCalendar();
		cal.set(Calendar.MONTH, 10); 
		cal.set(Calendar.DAY_OF_MONTH, 15);
		this.setSubDayFieldsZero(cal);
		Date endDate = cal.getTime();
		
		//one short, one long month name
		long[] result = this.parseTimes("00:00 Mar 1 ", "00:00 November 15");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);
		
	}

	/**
	 * Test named month dates with 2 digit years
	 * 
	 * NB: Seems silly to test all, just test that an arbitrary one works, in both short and long form
	 * If we find actual problems with specific months, we can add more tests
	 */
	@Test
	public void testNamedMonthsTwoDigitYear() {
		//Remember: 0-based month -- 1 = Feb
		Calendar cal = new GregorianCalendar(1980,1,2);
		Date startDate = cal.getTime();
		
		//9 = October 
		cal = new GregorianCalendar(1980,9,16);
		Date endDate = cal.getTime();
		
		long[] result = this.parseTimes("00:00 Feb 2 80", "00:00 October 16 80");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);
		
	}
	
	/**
	 * Test named month dates with 4 digit years
	 * 
	 * NB: Seems silly to test all, just test that an arbitrary one works, in both short and long form
	 * 
	 * If we find actual problems with specific months, we can add more tests
	 */
	@Test
	public void testNamedMonthsFourDigitYear() {
		//Remember: 0-based month -- 3 = April
		Calendar cal = new GregorianCalendar(1980,3,6);
		Date startDate = cal.getTime();
		
		//8 = Sept 
		cal = new GregorianCalendar(1980,8,17);
		Date endDate = cal.getTime();
		
		long[] result = this.parseTimes("00:00 Apr 6 1980", "00:00 September 17 1980");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);
		
	}
	
	/**
	 * Test day of week specification.  The expected behaviour is annoyingly murky; if these tests start failing
	 * give serious consideration to fixing the tests rather than the underlying code.
	 * 
	 */
	@Test
	public void testDayOfWeekTimeSpec() {
		Calendar cal = new GregorianCalendar();
		cal.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
		cal.set(Calendar.HOUR_OF_DAY, 12);
		this.setSubHourFieldsZero(cal);
		Date startDate = cal.getTime();

		cal = new GregorianCalendar();
		cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
		cal.set(Calendar.HOUR_OF_DAY, 18);
		this.setSubHourFieldsZero(cal);
		Date endDate = cal.getTime();

		
		long[] result = this.parseTimes("noon Thursday", "6pm Friday");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertEquals(startDate.getTime(), start);
		assertEquals(endDate.getTime(), end);
		
	}
	
	/**
	 * Test some basic time offsets
	 */
	@Test
	public void testTimeOffsets1() {
		Calendar cal = new GregorianCalendar();
		cal.setTimeInMillis(cal.getTimeInMillis()-60000);
		Date startDate = cal.getTime();
		
		cal = new GregorianCalendar();
		cal.setTimeInMillis(cal.getTimeInMillis()-10000);
		Date endDate = cal.getTime();
		
		long[] result = this.parseTimes("now - 1minute", "now-10 seconds");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");
		assertTimestampsEqualWithEpsilon(endDate.getTime(), end, 1000, "end");

	}
	
	/**
	 * Test some basic time offsets
	 * NB: Due to it's use of a "day" offset, this may fail around daylight savings time.
	 * Maybe (Depends how the parsing code constructs it's dates)
	 */
	@Test
	public void testTimeOffsets2() {
		Calendar cal = new GregorianCalendar();
		cal.setTimeInMillis(cal.getTimeInMillis()-ONE_DAY_IN_MILLIS);
		Date startDate = cal.getTime();
		
		cal = new GregorianCalendar();
		cal.setTimeInMillis(cal.getTimeInMillis()-(3*ONE_HOUR_IN_MILLIS));
		Date endDate = cal.getTime();
		
		long[] result = this.parseTimes("now - 1 day", "now-3 hours");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");
		assertTimestampsEqualWithEpsilon(endDate.getTime(), end, 1000, "end");

	}

	/**
	 * Test some basic time offsets
	 */
	@Test
	public void testTimeOffsets3() {
		Calendar cal = new GregorianCalendar();
		cal.set(Calendar.MONTH, 6);
		cal.set(Calendar.DAY_OF_MONTH, 12);
		cal.add(Calendar.MONTH, -1);
		Date startDate = cal.getTime();
		
		cal = new GregorianCalendar();
		cal.set(Calendar.MONTH, 6);
		cal.set(Calendar.DAY_OF_MONTH, 12);
		cal.add(Calendar.WEEK_OF_YEAR, -3);
		Date endDate = cal.getTime();
		
		long[] result = this.parseTimes("Jul 12 - 1 month", "Jul 12 - 3 weeks");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");
		assertTimestampsEqualWithEpsilon(endDate.getTime(), end, 1000, "end");

	}

	/**
	 * Test another basic time offset
	 */
	@Test
	public void testTimeOffsets4() {
		//Month 6 = July (0 offset)
		Calendar cal = new GregorianCalendar(1980, 6, 12);
		Date endDate = cal.getTime();
		
		cal = new GregorianCalendar(1979, 6, 12);
		Date startDate = cal.getTime();
		
		long[] result = this.parseTimes("end - 1 year", "00:00 12.07.1980");
		long start = result[0] * 1000;
		long end = result[1] * 1000;

		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");
		assertTimestampsEqualWithEpsilon(endDate.getTime(), end, 1000, "end");
	}
	
	/**
	 * Test some complex offset examples (per the rrdfetch man page)
	 */
	@Test
	public void complexTest1() {
		
		Calendar cal = new GregorianCalendar();
		cal.set(Calendar.HOUR_OF_DAY, 9);
		cal.add(Calendar.DAY_OF_YEAR, -1);
		setSubHourFieldsZero(cal);
		Date startDate = cal.getTime();
		

		long[] result = this.parseTimes("noon yesterday -3hours", "now");
		long start = result[0] * 1000;

		assertEquals(startDate.getTime(), start);
	}
	
	/**
	 * Test some more complex offset examples
	 */
	@Test
	public void complexTest2() {
		
		Calendar cal = new GregorianCalendar();
		cal.add(Calendar.HOUR, -5);
		cal.add(Calendar.MINUTE, -45);
		Date startDate = cal.getTime();

		long[] result = this.parseTimes("-5h45min", "now");
		long start = result[0] * 1000;

		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");
	}

	/**
	 * Test some more complex offset examples
	 */
	@Test
	public void complexTest3() {
		
		Calendar cal = new GregorianCalendar();
		cal.add(Calendar.MONTH, -5);
		cal.add(Calendar.WEEK_OF_YEAR, -1);
		cal.add(Calendar.DAY_OF_YEAR, -2);
		Date startDate = cal.getTime();

		long[] result = this.parseTimes("-5mon1w2d", "now");
		long start = result[0] * 1000;

		assertTimestampsEqualWithEpsilon(startDate.getTime(), start, 1000, "start");
	}

	
}
