Repository: flume Updated Branches: refs/heads/trunk ba64b1267 -> ec28b6624
FLUME-2725. HDFS Sink does not use configured timezone for rounding (Denes Arvay via Mike Percy) Project: http://git-wip-us.apache.org/repos/asf/flume/repo Commit: http://git-wip-us.apache.org/repos/asf/flume/commit/ec28b662 Tree: http://git-wip-us.apache.org/repos/asf/flume/tree/ec28b662 Diff: http://git-wip-us.apache.org/repos/asf/flume/diff/ec28b662 Branch: refs/heads/trunk Commit: ec28b66246f1f165ccaf01abf7fb27adebc9e4bb Parents: ba64b12 Author: Denes Arvay <[email protected]> Authored: Wed Jul 13 12:07:24 2016 -0700 Committer: Mike Percy <[email protected]> Committed: Wed Jul 13 12:09:46 2016 -0700 ---------------------------------------------------------------------- .../flume/formatter/output/BucketPath.java | 10 +- .../flume/tools/TimestampRoundDownUtil.java | 72 ++++++++++- .../flume/formatter/output/TestBucketPath.java | 119 +++++++++++++++--- .../flume/tools/TestTimestampRoundDownUtil.java | 124 +++++++++++++++---- 4 files changed, 275 insertions(+), 50 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flume/blob/ec28b662/flume-ng-core/src/main/java/org/apache/flume/formatter/output/BucketPath.java ---------------------------------------------------------------------- diff --git a/flume-ng-core/src/main/java/org/apache/flume/formatter/output/BucketPath.java b/flume-ng-core/src/main/java/org/apache/flume/formatter/output/BucketPath.java index b2fe3f0..167b542 100644 --- a/flume-ng-core/src/main/java/org/apache/flume/formatter/output/BucketPath.java +++ b/flume-ng-core/src/main/java/org/apache/flume/formatter/output/BucketPath.java @@ -236,7 +236,7 @@ public class BucketPath { } if (needRounding) { - ts = roundDown(roundDown, unit, ts); + ts = roundDown(roundDown, unit, ts, timeZone); } // It's a date @@ -329,7 +329,7 @@ public class BucketPath { return format.format(date); } - private static long roundDown(int roundDown, int unit, long ts) { + private static long roundDown(int roundDown, int unit, long ts, TimeZone timeZone) { long timestamp = ts; if (roundDown <= 0) { roundDown = 1; @@ -337,15 +337,15 @@ public class BucketPath { switch (unit) { case Calendar.SECOND: timestamp = TimestampRoundDownUtil.roundDownTimeStampSeconds( - ts, roundDown); + ts, roundDown, timeZone); break; case Calendar.MINUTE: timestamp = TimestampRoundDownUtil.roundDownTimeStampMinutes( - ts, roundDown); + ts, roundDown, timeZone); break; case Calendar.HOUR_OF_DAY: timestamp = TimestampRoundDownUtil.roundDownTimeStampHours( - ts, roundDown); + ts, roundDown, timeZone); break; default: timestamp = ts; http://git-wip-us.apache.org/repos/asf/flume/blob/ec28b662/flume-ng-core/src/main/java/org/apache/flume/tools/TimestampRoundDownUtil.java ---------------------------------------------------------------------- diff --git a/flume-ng-core/src/main/java/org/apache/flume/tools/TimestampRoundDownUtil.java b/flume-ng-core/src/main/java/org/apache/flume/tools/TimestampRoundDownUtil.java index daa9606..6ce0fb9 100644 --- a/flume-ng-core/src/main/java/org/apache/flume/tools/TimestampRoundDownUtil.java +++ b/flume-ng-core/src/main/java/org/apache/flume/tools/TimestampRoundDownUtil.java @@ -19,25 +19,47 @@ package org.apache.flume.tools; import java.util.Calendar; +import java.util.TimeZone; import com.google.common.base.Preconditions; +import org.apache.flume.annotations.InterfaceAudience; +import org.apache.flume.annotations.InterfaceStability; [email protected] [email protected] public class TimestampRoundDownUtil { /** * * @param timestamp - The time stamp to be rounded down. + * For parsing the <tt>timestamp</tt> the system default timezone will be used. * @param roundDownSec - The <tt>timestamp</tt> is rounded down to the largest * multiple of <tt>roundDownSec</tt> seconds * less than or equal to <tt>timestamp.</tt> Should be between 0 and 60. * @return - Rounded down timestamp * @throws IllegalStateException + * @see TimestampRoundDownUtil#roundDownTimeStampSeconds(long, int, TimeZone) */ public static long roundDownTimeStampSeconds(long timestamp, int roundDownSec) throws IllegalStateException { + return roundDownTimeStampSeconds(timestamp, roundDownSec, null); + } + + /** + * + * @param timestamp - The time stamp to be rounded down. + * @param roundDownSec - The <tt>timestamp</tt> is rounded down to the largest + * multiple of <tt>roundDownSec</tt> seconds + * less than or equal to <tt>timestamp.</tt> Should be between 0 and 60. + * @param timeZone - The timezone to use for parsing the <tt>timestamp</tt>. + * @return - Rounded down timestamp + * @throws IllegalStateException + */ + public static long roundDownTimeStampSeconds(long timestamp, int roundDownSec, TimeZone timeZone) + throws IllegalStateException { Preconditions.checkArgument(roundDownSec > 0 && roundDownSec <= 60, "RoundDownSec must be > 0 and <=60"); - Calendar cal = roundDownField(timestamp, Calendar.SECOND, roundDownSec); + Calendar cal = roundDownField(timestamp, Calendar.SECOND, roundDownSec, timeZone); cal.set(Calendar.MILLISECOND, 0); return cal.getTimeInMillis(); } @@ -45,17 +67,35 @@ public class TimestampRoundDownUtil { /** * * @param timestamp - The time stamp to be rounded down. + * For parsing the <tt>timestamp</tt> the system default timezone will be used. * @param roundDownMins - The <tt>timestamp</tt> is rounded down to the * largest multiple of <tt>roundDownMins</tt> minutes less than * or equal to <tt>timestamp.</tt> Should be between 0 and 60. * @return - Rounded down timestamp * @throws IllegalStateException + * @see TimestampRoundDownUtil#roundDownTimeStampMinutes(long, int, TimeZone) */ public static long roundDownTimeStampMinutes(long timestamp, int roundDownMins) throws IllegalStateException { + return roundDownTimeStampMinutes(timestamp, roundDownMins, null); + } + + /** + * + * @param timestamp - The time stamp to be rounded down. + * @param roundDownMins - The <tt>timestamp</tt> is rounded down to the + * largest multiple of <tt>roundDownMins</tt> minutes less than + * or equal to <tt>timestamp.</tt> Should be between 0 and 60. + * @param timeZone - The timezone to use for parsing the <tt>timestamp</tt>. + * If <tt>null</tt> the system default will be used. + * @return - Rounded down timestamp + * @throws IllegalStateException + */ + public static long roundDownTimeStampMinutes(long timestamp, int roundDownMins, TimeZone timeZone) + throws IllegalStateException { Preconditions.checkArgument(roundDownMins > 0 && roundDownMins <= 60, "RoundDown must be > 0 and <=60"); - Calendar cal = roundDownField(timestamp, Calendar.MINUTE, roundDownMins); + Calendar cal = roundDownField(timestamp, Calendar.MINUTE, roundDownMins, timeZone); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTimeInMillis(); @@ -65,28 +105,48 @@ public class TimestampRoundDownUtil { /** * * @param timestamp - The time stamp to be rounded down. + * For parsing the <tt>timestamp</tt> the system default timezone will be used. * @param roundDownHours - The <tt>timestamp</tt> is rounded down to the * largest multiple of <tt>roundDownHours</tt> hours less than * or equal to <tt>timestamp.</tt> Should be between 0 and 24. * @return - Rounded down timestamp * @throws IllegalStateException + * @see TimestampRoundDownUtil#roundDownTimeStampHours(long, int, TimeZone) */ public static long roundDownTimeStampHours(long timestamp, int roundDownHours) throws IllegalStateException { + return roundDownTimeStampHours(timestamp, roundDownHours, null); + } + + /** + * + * @param timestamp - The time stamp to be rounded down. + * @param roundDownHours - The <tt>timestamp</tt> is rounded down to the + * largest multiple of <tt>roundDownHours</tt> hours less than + * or equal to <tt>timestamp.</tt> Should be between 0 and 24. + * @param timeZone - The timezone to use for parsing the <tt>timestamp</tt>. + * If <tt>null</tt> the system default will be used. + * @return - Rounded down timestamp + * @throws IllegalStateException + */ + public static long roundDownTimeStampHours(long timestamp, int roundDownHours, TimeZone timeZone) + throws IllegalStateException { Preconditions.checkArgument(roundDownHours > 0 && roundDownHours <= 24, "RoundDown must be > 0 and <=24"); - Calendar cal = roundDownField(timestamp, - Calendar.HOUR_OF_DAY, roundDownHours); + Calendar cal = roundDownField(timestamp, Calendar.HOUR_OF_DAY, roundDownHours, timeZone); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTimeInMillis(); } - private static Calendar roundDownField(long timestamp, int field, int roundDown) { + private static Calendar roundDownField(long timestamp, int field, int roundDown, + TimeZone timeZone) { Preconditions.checkArgument(timestamp > 0, "Timestamp must be positive"); - Calendar cal = Calendar.getInstance(); + + Calendar cal = (timeZone == null) ? Calendar.getInstance() : Calendar.getInstance(timeZone); cal.setTimeInMillis(timestamp); + int fieldVal = cal.get(field); int remainder = (fieldVal % roundDown); cal.set(field, fieldVal - remainder); http://git-wip-us.apache.org/repos/asf/flume/blob/ec28b662/flume-ng-core/src/test/java/org/apache/flume/formatter/output/TestBucketPath.java ---------------------------------------------------------------------- diff --git a/flume-ng-core/src/test/java/org/apache/flume/formatter/output/TestBucketPath.java b/flume-ng-core/src/test/java/org/apache/flume/formatter/output/TestBucketPath.java index b1b828a..ccc7460 100644 --- a/flume-ng-core/src/test/java/org/apache/flume/formatter/output/TestBucketPath.java +++ b/flume-ng-core/src/test/java/org/apache/flume/formatter/output/TestBucketPath.java @@ -25,29 +25,40 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import javax.annotation.Nullable; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.SimpleTimeZone; import java.util.TimeZone; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class TestBucketPath { - Calendar cal; - Map<String, String> headers; + private static final TimeZone CUSTOM_TIMEZONE = new SimpleTimeZone(1, "custom-timezone"); + + private Calendar cal; + private Map<String, String> headers; + private Map<String, String> headersWithTimeZone; @Before public void setUp() { - cal = Calendar.getInstance(); - cal.set(2012, 5, 23, 13, 46, 33); - cal.set(Calendar.MILLISECOND, 234); - headers = new HashMap<String, String>(); + cal = createCalendar(2012, 5, 23, 13, 46, 33, 234, null); + headers = new HashMap<>(); headers.put("timestamp", String.valueOf(cal.getTimeInMillis())); + + Calendar calWithTimeZone = createCalendar(2012, 5, 23, 13, 46, 33, 234, CUSTOM_TIMEZONE); + headersWithTimeZone = new HashMap<>(); + headersWithTimeZone.put("timestamp", String.valueOf(calWithTimeZone.getTimeInMillis())); } + /** + * Tests if the internally cached SimpleDateFormat instances can be reused with different + * TimeZone without interference. + */ @Test public void testDateFormatCache() { TimeZone utcTimeZone = TimeZone.getTimeZone("UTC"); @@ -64,15 +75,19 @@ public class TestBucketPath { Assert.assertEquals(expectedString, escapedString); } + /** + * Tests if the timestamp with the default timezone is properly rounded down + * to 12 hours using "%c" ("EEE MMM d HH:mm:ss yyyy") formatting. + */ @Test public void testDateFormatHours() { String test = "%c"; String escapedString = BucketPath.escapeString( test, headers, true, Calendar.HOUR_OF_DAY, 12); System.out.println("Escaped String: " + escapedString); - Calendar cal2 = Calendar.getInstance(); - cal2.set(2012, 5, 23, 12, 0, 0); - cal2.set(Calendar.MILLISECOND, 0); + + Calendar cal2 = createCalendar(2012, 5, 23, 12, 0, 0, 0, null); + SimpleDateFormat format = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy"); Date d = new Date(cal2.getTimeInMillis()); String expectedString = format.format(d); @@ -80,34 +95,99 @@ public class TestBucketPath { Assert.assertEquals(expectedString, escapedString); } + /** + * Tests if the timestamp with the custom timezone is properly rounded down + * to 12 hours using "%c" ("EEE MMM d HH:mm:ss yyyy") formatting. + */ + @Test + public void testDateFormatHoursTimeZone() { + String test = "%c"; + String escapedString = BucketPath.escapeString( + test, headersWithTimeZone, CUSTOM_TIMEZONE, true, Calendar.HOUR_OF_DAY, 12, false); + System.out.println("Escaped String: " + escapedString); + + Calendar cal2 = createCalendar(2012, 5, 23, 12, 0, 0, 0, CUSTOM_TIMEZONE); + + SimpleDateFormat format = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy"); + format.setTimeZone(CUSTOM_TIMEZONE); + + Date d = new Date(cal2.getTimeInMillis()); + String expectedString = format.format(d); + System.out.println("Expected String: " + expectedString); + Assert.assertEquals(expectedString, escapedString); + } + + /** + * Tests if the timestamp with the default timezone is properly rounded down + * to 5 minutes using "%s" (seconds) formatting + */ @Test public void testDateFormatMinutes() { String test = "%s"; String escapedString = BucketPath.escapeString( test, headers, true, Calendar.MINUTE, 5); System.out.println("Escaped String: " + escapedString); - Calendar cal2 = Calendar.getInstance(); - cal2.set(2012, 5, 23, 13, 45, 0); - cal2.set(Calendar.MILLISECOND, 0); + + Calendar cal2 = createCalendar(2012, 5, 23, 13, 45, 0, 0, null); + String expectedString = String.valueOf(cal2.getTimeInMillis() / 1000); + System.out.println("Expected String: " + expectedString); + Assert.assertEquals(expectedString, escapedString); + } + + /** + * Tests if the timestamp with the custom timezone is properly rounded down + * to 5 minutes using "%s" (seconds) formatting + */ + @Test + public void testDateFormatMinutesTimeZone() { + String test = "%s"; + String escapedString = BucketPath.escapeString( + test, headersWithTimeZone, CUSTOM_TIMEZONE, true, Calendar.MINUTE, 5, false); + System.out.println("Escaped String: " + escapedString); + + Calendar cal2 = createCalendar(2012, 5, 23, 13, 45, 0, 0, CUSTOM_TIMEZONE); String expectedString = String.valueOf(cal2.getTimeInMillis() / 1000); System.out.println("Expected String: " + expectedString); Assert.assertEquals(expectedString, escapedString); } + /** + * Tests if the timestamp with the default timezone is properly rounded down + * to 5 seconds using "%s" (seconds) formatting + */ @Test public void testDateFormatSeconds() { String test = "%s"; String escapedString = BucketPath.escapeString( test, headers, true, Calendar.SECOND, 5); System.out.println("Escaped String: " + escapedString); - Calendar cal2 = Calendar.getInstance(); - cal2.set(2012, 5, 23, 13, 46, 30); - cal2.set(Calendar.MILLISECOND, 0); + + Calendar cal2 = createCalendar(2012, 5, 23, 13, 46, 30, 0, null); String expectedString = String.valueOf(cal2.getTimeInMillis() / 1000); System.out.println("Expected String: " + expectedString); Assert.assertEquals(expectedString, escapedString); } + /** + * Tests if the timestamp with the custom timezone is properly rounded down + * to 5 seconds using "%s" (seconds) formatting + */ + @Test + public void testDateFormatSecondsTimeZone() { + String test = "%s"; + String escapedString = BucketPath.escapeString( + test, headersWithTimeZone, CUSTOM_TIMEZONE, true, Calendar.SECOND, 5, false); + System.out.println("Escaped String: " + escapedString); + + Calendar cal2 = createCalendar(2012, 5, 23, 13, 46, 30, 0, CUSTOM_TIMEZONE); + String expectedString = String.valueOf(cal2.getTimeInMillis() / 1000); + System.out.println("Expected String: " + expectedString); + Assert.assertEquals(expectedString, escapedString); + } + + /** + * Tests if the timestamp is properly formatted without rounding it down. + */ @Test public void testNoRounding() { String test = "%c"; @@ -189,4 +269,13 @@ public class TestBucketPath { Assert.assertEquals("Race condition detected", "02:50", escaped); } + + private static Calendar createCalendar(int year, int month, int day, + int hour, int minute, int second, int ms, + @Nullable TimeZone timeZone) { + Calendar cal = (timeZone == null) ? Calendar.getInstance() : Calendar.getInstance(timeZone); + cal.set(year, month, day, hour, minute, second); + cal.set(Calendar.MILLISECOND, ms); + return cal; + } } http://git-wip-us.apache.org/repos/asf/flume/blob/ec28b662/flume-ng-core/src/test/java/org/apache/flume/tools/TestTimestampRoundDownUtil.java ---------------------------------------------------------------------- diff --git a/flume-ng-core/src/test/java/org/apache/flume/tools/TestTimestampRoundDownUtil.java b/flume-ng-core/src/test/java/org/apache/flume/tools/TestTimestampRoundDownUtil.java index 1ac11ab..384a9dc 100644 --- a/flume-ng-core/src/test/java/org/apache/flume/tools/TestTimestampRoundDownUtil.java +++ b/flume-ng-core/src/test/java/org/apache/flume/tools/TestTimestampRoundDownUtil.java @@ -19,23 +19,36 @@ package org.apache.flume.tools; import java.util.Calendar; +import java.util.SimpleTimeZone; +import java.util.TimeZone; import junit.framework.Assert; import org.junit.Test; +import javax.annotation.Nullable; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertThat; + public class TestTimestampRoundDownUtil { + private static final TimeZone CUSTOM_TIMEZONE = new SimpleTimeZone(1, "custom-timezone"); + private static final Calendar BASE_CALENDAR_WITH_DEFAULT_TIMEZONE = + createCalendar(2012, 5, 15, 15, 12, 54, 0, null); + private static final Calendar BASE_CALENDAR_WITH_CUSTOM_TIMEZONE = + createCalendar(2012, 5, 15, 15, 12, 54, 0, CUSTOM_TIMEZONE); + + /** + * Tests if the timestamp with the default timezone is properly rounded down + * to 60 seconds. + */ @Test public void testRoundDownTimeStampSeconds() { - Calendar cal = Calendar.getInstance(); - cal.clear(); - cal.set(2012, 5, 15, 15, 12, 54); - cal.set(Calendar.MILLISECOND, 20); - Calendar cal2 = Calendar.getInstance(); - cal2.clear(); - cal2.set(2012, 5, 15, 15, 12, 0); - cal2.set(Calendar.MILLISECOND, 0); + Calendar cal = BASE_CALENDAR_WITH_DEFAULT_TIMEZONE; + Calendar cal2 = createCalendar(2012, 5, 15, 15, 12, 0, 0, null); + long timeToVerify = cal2.getTimeInMillis(); long ret = TimestampRoundDownUtil.roundDownTimeStampSeconds(cal.getTimeInMillis(), 60); System.out.println("Cal 1: " + cal.toString()); @@ -43,16 +56,34 @@ public class TestTimestampRoundDownUtil { Assert.assertEquals(timeToVerify, ret); } + /** + * Tests if the timestamp with the custom timezone is properly rounded down + * to 60 seconds. + */ + @Test + public void testRoundDownTimeStampSecondsWithTimeZone() { + Calendar cal = BASE_CALENDAR_WITH_CUSTOM_TIMEZONE; + Calendar cal2 = createCalendar(2012, 5, 15, 15, 12, 0, 0, CUSTOM_TIMEZONE); + + long timeToVerify = cal2.getTimeInMillis(); + long withoutTimeZone = TimestampRoundDownUtil.roundDownTimeStampSeconds( + cal.getTimeInMillis(), 60); + long withTimeZone = TimestampRoundDownUtil.roundDownTimeStampSeconds( + cal.getTimeInMillis(), 60, CUSTOM_TIMEZONE); + + assertThat(withoutTimeZone, not(equalTo(timeToVerify))); + Assert.assertEquals(withTimeZone, timeToVerify); + } + + /** + * Tests if the timestamp with the default timezone is properly rounded down + * to 5 minutes. + */ @Test public void testRoundDownTimeStampMinutes() { - Calendar cal = Calendar.getInstance(); - cal.clear(); - cal.set(2012, 5, 15, 15, 12, 54); - cal.set(Calendar.MILLISECOND, 20); - Calendar cal2 = Calendar.getInstance(); - cal2.clear(); - cal2.set(2012, 5, 15, 15, 10, 0); - cal2.set(Calendar.MILLISECOND, 0); + Calendar cal = BASE_CALENDAR_WITH_DEFAULT_TIMEZONE; + Calendar cal2 = createCalendar(2012, 5, 15, 15, 10, 0, 0, null); + long timeToVerify = cal2.getTimeInMillis(); long ret = TimestampRoundDownUtil.roundDownTimeStampMinutes(cal.getTimeInMillis(), 5); System.out.println("Cal 1: " + cal.toString()); @@ -60,16 +91,34 @@ public class TestTimestampRoundDownUtil { Assert.assertEquals(timeToVerify, ret); } + /** + * Tests if the timestamp with the custom timezone is properly rounded down + * to 5 minutes. + */ + @Test + public void testRoundDownTimeStampMinutesWithTimeZone() { + Calendar cal = BASE_CALENDAR_WITH_CUSTOM_TIMEZONE; + Calendar cal2 = createCalendar(2012, 5, 15, 15, 10, 0, 0, CUSTOM_TIMEZONE); + + long timeToVerify = cal2.getTimeInMillis(); + long withoutTimeZone = TimestampRoundDownUtil.roundDownTimeStampMinutes( + cal.getTimeInMillis(), 5); + long withTimeZone = TimestampRoundDownUtil.roundDownTimeStampMinutes( + cal.getTimeInMillis(), 5, CUSTOM_TIMEZONE); + + assertThat(withoutTimeZone, not(equalTo(timeToVerify))); + Assert.assertEquals(withTimeZone, timeToVerify); + } + + /** + * Tests if the timestamp with the default timezone is properly rounded down + * to 2 hours. + */ @Test public void testRoundDownTimeStampHours() { - Calendar cal = Calendar.getInstance(); - cal.clear(); - cal.set(2012, 5, 15, 15, 12, 54); - cal.set(Calendar.MILLISECOND, 20); - Calendar cal2 = Calendar.getInstance(); - cal2.clear(); - cal2.set(2012, 5, 15, 14, 0, 0); - cal2.set(Calendar.MILLISECOND, 0); + Calendar cal = BASE_CALENDAR_WITH_DEFAULT_TIMEZONE; + Calendar cal2 = createCalendar(2012, 5, 15, 14, 0, 0, 0, null); + long timeToVerify = cal2.getTimeInMillis(); long ret = TimestampRoundDownUtil.roundDownTimeStampHours(cal.getTimeInMillis(), 2); System.out.println("Cal 1: " + ret); @@ -77,4 +126,31 @@ public class TestTimestampRoundDownUtil { Assert.assertEquals(timeToVerify, ret); } + /** + * Tests if the timestamp with the custom timezone is properly rounded down + * to 2 hours. + */ + @Test + public void testRoundDownTimeStampHoursWithTimeZone() { + Calendar cal = BASE_CALENDAR_WITH_CUSTOM_TIMEZONE; + Calendar cal2 = createCalendar(2012, 5, 15, 14, 0, 0, 0, CUSTOM_TIMEZONE); + + long timeToVerify = cal2.getTimeInMillis(); + long withoutTimeZone = TimestampRoundDownUtil.roundDownTimeStampHours( + cal.getTimeInMillis(), 2); + long withTimeZone = TimestampRoundDownUtil.roundDownTimeStampHours( + cal.getTimeInMillis(), 2, CUSTOM_TIMEZONE); + + assertThat(withoutTimeZone, not(equalTo(timeToVerify))); + Assert.assertEquals(withTimeZone, timeToVerify); + } + + private static Calendar createCalendar(int year, int month, int day, + int hour, int minute, int second, int ms, + @Nullable TimeZone timeZone) { + Calendar cal = (timeZone == null) ? Calendar.getInstance() : Calendar.getInstance(timeZone); + cal.set(year, month, day, hour, minute, second); + cal.set(Calendar.MILLISECOND, ms); + return cal; + } }
