/****************************************************************************
* Copyright (c) 2012 Scott Klein
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Scott Klein <scott.klein@goldenhour.com> - initial API and implementation
*****************************************************************************/
package org.eclipse.nebula.widgets.cdatetime;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.TimeZone;
import org.eclipse.nebula.cwt.test.AbstractVTestCase;
import org.eclipse.swt.SWT;
public class Bug370605 extends AbstractVTestCase {
private static final String FALL_EPOCH = "11/04/2012 00:00.00 PDT";
private static Date now = new Date();
private static final String PATTERN_TIMESTAMP = "MM/dd/yyyy HH:mm.ss z";
private static final String SPRING_EPOCH = "03/11/2012 01:00.00 PST";
private static final TimeZone TIMEZONE_DST = TimeZone
.getTimeZone("US/Pacific");
private static final TimeZone TIMEZONE_INITIAL = TimeZone
.getTimeZone("Pacific/Kiritimati");
private static Collection<TimeZone> timezones = new ArrayList<TimeZone>();
private static final String[] TIMEZONES = { "UTC", "MIT", "HST", "AST",
"PST", "MST", "CST", "EST", "PRT", "AGT", "BET", "CET", "EET",
"NET", "IST", "VST", "JST", "NST" };
private CdtTester tester;
/**
* Using traverse arrow keys, move through each field of the control
*
* Stop traversing if we have cycled back to the starting field, or we reach
* the time zone field
*
* @return true, if the time zone field has been found. false otherwise.
*/
private boolean moveToTimeZoneField(int calendarFieldSelection) {
CDateTime cdt = tester.getCDateTime();
int initialField = cdt.getCalendarField();
int currentField = -1;
do {
keyPress(SWT.ARROW_RIGHT);
keyPress('\r');
currentField = cdt.getCalendarField();
} while (currentField != initialField
&& currentField != calendarFieldSelection);
return currentField != Calendar.ZONE_OFFSET;
}
public void setUp() throws Exception {
timezones.clear();
for (final String timezone : TIMEZONES) {
timezones.add(TimeZone.getTimeZone(timezone));
}
tester = new CdtTester(getShell(), CDT.BORDER | CDT.TAB_FIELDS
| CDT.CLOCK_24_HOUR | CDT.DATE_LONG | CDT.TIME_MEDIUM);
}
/**
* This uses a single test with a known DST zone (PST).
*
* <ol>
* Test Plans
* <li>roll over the epoch time and ensure we roll over both 1 AM times
* (Daylight and Standard).</li>
* <li>roll backwards and ensure we can do that also</li>
* <li>manually type in the epoch time and ensure we get the Java default
* time</li>
* </ol>
*
* @throws Exception
*/
public void testDaylightSavingsFallRoll() throws Exception {
TimeZone.setDefault(TIMEZONE_DST);
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN_TIMESTAMP);
Date fallEpochDate = sdf.parse(FALL_EPOCH);
Calendar fallEpochCal = Calendar.getInstance();
fallEpochCal.setTime(fallEpochDate);
tester.setPattern(PATTERN_TIMESTAMP);
tester.setTimeZone(TIMEZONE_DST);
tester.setSelection(fallEpochDate);
click(tester.getTextWidget());
moveToTimeZoneField(Calendar.HOUR_OF_DAY);
// VERIFY: Move from 12 AM to 1 AM
// Ignoring time zone DST during this test
keyPress(SWT.ARROW_UP);
keyPress('\r');
Date modifiedDate = tester.getCDateTime().getCalendarTime();
Calendar modifiedCal = Calendar.getInstance();
modifiedCal.setTime(modifiedDate);
assertEquals(fallEpochCal.get(Calendar.HOUR_OF_DAY) + 1,
modifiedCal.get(Calendar.HOUR_OF_DAY));
// VERFIY: Move from 1 AM to 1 AM
// Ignoring time zone DST during this test
keyPress(SWT.ARROW_UP);
keyPress('\r');
modifiedDate = tester.getCDateTime().getCalendarTime();
modifiedCal = Calendar.getInstance();
modifiedCal.setTime(modifiedDate);
assertEquals(fallEpochCal.get(Calendar.HOUR_OF_DAY) + 1,
modifiedCal.get(Calendar.HOUR_OF_DAY));
// VERIFY: Move from 1 AM to 2 AM
keyPress(SWT.ARROW_UP);
keyPress('\r');
modifiedDate = tester.getCDateTime().getCalendarTime();
modifiedCal = Calendar.getInstance();
modifiedCal.setTime(modifiedDate);
assertEquals(fallEpochCal.get(Calendar.HOUR_OF_DAY) + 2,
modifiedCal.get(Calendar.HOUR_OF_DAY));
// VERIFY: Move backwards from 2 AM to 1 AM
keyPress(SWT.ARROW_DOWN);
keyPress('\r');
modifiedDate = tester.getCDateTime().getCalendarTime();
modifiedCal = Calendar.getInstance();
modifiedCal.setTime(modifiedDate);
assertEquals(fallEpochCal.get(Calendar.HOUR_OF_DAY) + 1,
modifiedCal.get(Calendar.HOUR_OF_DAY));
// VERIFY: Move backwards from 1 AM to 1 AM
keyPress(SWT.ARROW_DOWN);
keyPress('\r');
modifiedDate = tester.getCDateTime().getCalendarTime();
modifiedCal = Calendar.getInstance();
modifiedCal.setTime(modifiedDate);
assertEquals(fallEpochCal.get(Calendar.HOUR_OF_DAY) + 1,
modifiedCal.get(Calendar.HOUR_OF_DAY));
// VERIFY: Move backwards from 1 AM to 12 AM
keyPress(SWT.ARROW_DOWN);
keyPress('\r');
modifiedDate = tester.getCDateTime().getCalendarTime();
modifiedCal = Calendar.getInstance();
modifiedCal.setTime(modifiedDate);
assertEquals(fallEpochCal.get(Calendar.HOUR_OF_DAY),
modifiedCal.get(Calendar.HOUR_OF_DAY));
// VERIFY: Manually type in 1 AM
keyPress(SWT.KEYPAD_0);
keyPress(SWT.KEYPAD_1);
keyPress('\r');
modifiedDate = tester.getCDateTime().getCalendarTime();
modifiedCal = Calendar.getInstance();
modifiedCal.setTime(modifiedDate);
assertEquals(1, modifiedCal.get(Calendar.HOUR_OF_DAY));
}
/**
* This uses a single test with a known DST zone (PST).
*
* <ol>
* Test Plans
* <li>roll over the epoch time and ensure we roll over 1 AM directly into 3
* AM</li>
* <li>roll backwards and ensure we can do that also</li>
* <li>manually type in the epoch time and ensure we get the Java default
* time</li>
* </ol>
*
* @throws Exception
*/
public void testDaylightSavingsSpringRoll() throws Exception {
TimeZone.setDefault(TIMEZONE_DST);
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN_TIMESTAMP);
Date springEpochDate = sdf.parse(SPRING_EPOCH);
Calendar springEpochCal = Calendar.getInstance();
springEpochCal.setTime(springEpochDate);
tester.setPattern(PATTERN_TIMESTAMP);
tester.setTimeZone(TIMEZONE_DST);
tester.setSelection(springEpochDate);
click(tester.getTextWidget());
moveToTimeZoneField(Calendar.HOUR_OF_DAY);
// VERIFY: Spring from 1 AM to 3 AM using arrow keys
keyPress(SWT.ARROW_UP);
keyPress('\r');
Date modifiedDate = tester.getCDateTime().getCalendarTime();
Calendar modifiedCal = Calendar.getInstance();
modifiedCal.setTime(modifiedDate);
assertEquals(springEpochCal.get(Calendar.HOUR_OF_DAY) + 2,
modifiedCal.get(Calendar.HOUR_OF_DAY));
// VERIFY: Spring backwards from 3 AM to 1 AM using arrow keys
keyPress(SWT.ARROW_DOWN);
keyPress('\r');
modifiedDate = tester.getCDateTime().getCalendarTime();
modifiedCal = Calendar.getInstance();
modifiedCal.setTime(modifiedDate);
assertEquals(springEpochCal.get(Calendar.HOUR_OF_DAY),
modifiedCal.get(Calendar.HOUR_OF_DAY));
// VERIFY: Manully enter 2 AM and verify it reverts to 3 AM
keyPress(SWT.KEYPAD_0);
keyPress(SWT.KEYPAD_2);
modifiedDate = tester.getCDateTime().getCalendarTime();
modifiedCal = Calendar.getInstance();
modifiedCal.setTime(modifiedDate);
assertEquals(3, modifiedCal.get(Calendar.HOUR_OF_DAY));
}
/**
* Using a CDateTime that is not configured for altering time zone, verify
* that the time zone field is simply not able to be traversed into.
*
* @throws Exception
*/
public void testNoTimeZoneSelection() throws Exception {
tester.setPattern(PATTERN_TIMESTAMP);
tester.setTimeZone(TIMEZONE_INITIAL);
tester.setSelection(now);
click(tester.getTextWidget());
// VERIFY: TimeZone is set to the initial time zone
final TimeZone wtzOriginal = tester.getCDateTime().getTimeZone();
assertEquals(TIMEZONE_INITIAL.getDisplayName(),
wtzOriginal.getDisplayName());
// VERIFY: Move over to time zone, but this should not be
// possible, so the utility method should return false
assertTrue(moveToTimeZoneField(Calendar.ZONE_OFFSET));
}
/**
* Using a CDateTime that is configured for altering the time zone, verify
* that our original time zone that we set to the control is still in the
* control on instantiation. Here we use a time zone that is *not* in the
* list to ensure we do no alter the programatic expectation.
*
* We then step over to the time zone field and verify that the controls
* time zone is altered in accordance with our list of time zones that we
* set into the control
*
* @throws Exception
*/
public void testTimeZoneSelection() throws Exception {
tester.setPattern(PATTERN_TIMESTAMP, timezones.toArray(new TimeZone[0]));
tester.setTimeZone(TIMEZONE_INITIAL);
tester.setSelection(now);
// VERIFY: TimeZone is set to the initial time zone
final TimeZone wtzOriginal = tester.getCDateTime().getTimeZone();
assertEquals(TIMEZONE_INITIAL.getDisplayName(),
wtzOriginal.getDisplayName());
// Move to the TimeZone field
click(tester.getTextWidget());
moveToTimeZoneField(Calendar.ZONE_OFFSET);
SimpleDateFormat sdf = new SimpleDateFormat("z");
// VERIFY: Flip forward through each available timezone and that it
// changes in the control
for (String timezone : TIMEZONES) {
keyPress(SWT.ARROW_UP);
keyPress('\r');
final TimeZone actualTimeZone = tester.getCDateTime().getTimeZone();
final TimeZone expectedTimeZone = TimeZone.getTimeZone(timezone);
// get the actual timezone format we expect, and the actual one
sdf.setTimeZone(actualTimeZone);
final String actualTimeZoneDisplay = sdf.format(new Date());
sdf.setTimeZone(expectedTimeZone);
final String expectedTimeZoneDisplay = sdf.format(new Date());
assertEquals(actualTimeZoneDisplay, expectedTimeZoneDisplay);
}
// Get back to the "1st" time zone in the list
keyPress(SWT.ARROW_UP);
keyPress('\r');
// VERIFY: Flip backward through each available timezone and that it
// changes in the control
for (int idx = TIMEZONES.length - 1; idx >= 0; idx--) {
keyPress(SWT.ARROW_DOWN);
keyPress('\r');
final TimeZone actualTimeZone = tester.getCDateTime().getTimeZone();
final TimeZone expectedTimeZone = TimeZone
.getTimeZone(TIMEZONES[idx]);
// get the actual timezone format we expect, and the actual one
sdf.setTimeZone(actualTimeZone);
final String actualTimeZoneDisplay = sdf.format(new Date());
sdf.setTimeZone(expectedTimeZone);
final String expectedTimeZoneDisplay = sdf.format(new Date());
assertEquals(actualTimeZoneDisplay, expectedTimeZoneDisplay);
}
}
}