From 1b49305b6af43772d002da9a4fd81d58f067dd86 Mon Sep 17 00:00:00 2001
From: Tim Molter <tim.molter@gmail.com>
Date: Mon, 14 Jan 2013 09:42:22 +0100
Subject: [PATCH] cleaned up date formatting

---
 .../xeiam/xchart/demo/charts/Example4.java    |  2 +
 .../src/main/java/com/xeiam/xchart/Chart.java | 14 +++++-
 .../xchart/internal/chartpart/AxisTick.java   |  8 +++-
 .../internal/misc/AxisValueFormatterUtil.java | 39 ++++++++--------
 .../com/xeiam/xchart/ValueFormatTest.java     | 45 +++++++++----------
 5 files changed, 64 insertions(+), 44 deletions(-)

diff --git a/xchart-examples/src/main/java/com/xeiam/xchart/demo/charts/Example4.java b/xchart-examples/src/main/java/com/xeiam/xchart/demo/charts/Example4.java
index 7c03d352..433e9bf1 100644
--- a/xchart-examples/src/main/java/com/xeiam/xchart/demo/charts/Example4.java
+++ b/xchart-examples/src/main/java/com/xeiam/xchart/demo/charts/Example4.java
@@ -21,6 +21,7 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
+import java.util.TimeZone;
 
 import com.xeiam.xchart.Chart;
 import com.xeiam.xchart.Series;
@@ -67,6 +68,7 @@ public class Example4 implements ExampleChart {
     chart.setTitle("Example4");
     chart.setXAxisTitle("time of day");
     chart.setYAxisTitle("gigawatts");
+    chart.setTimezone(TimeZone.getTimeZone("UTC"));
 
     Series series = chart.addDateSeries("value", xData, yData);
 
diff --git a/xchart/src/main/java/com/xeiam/xchart/Chart.java b/xchart/src/main/java/com/xeiam/xchart/Chart.java
index fc76c8b4..9d2edcbc 100644
--- a/xchart/src/main/java/com/xeiam/xchart/Chart.java
+++ b/xchart/src/main/java/com/xeiam/xchart/Chart.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
 import java.util.Locale;
+import java.util.TimeZone;
 
 import com.xeiam.xchart.internal.chartpart.AxisPair;
 import com.xeiam.xchart.internal.chartpart.ChartTitle;
@@ -462,7 +463,7 @@ public class Chart {
   /**
    * Set the locale to use for rendering the chart
    * 
-   * @param locale - the locale to use when drawing the chart
+   * @param locale - the locale to use when formatting Strings and dates for the axis tick labels
    */
   public void setLocale(Locale locale) {
 
@@ -470,4 +471,15 @@ public class Chart {
     this.axisPair.yAxis.axisTick.locale = locale;
   }
 
+  /**
+   * Set the timezone to use for formatting Date axis tick labels
+   * 
+   * @param timezone the timezone to use when formatting date data
+   */
+  public void setTimezone(TimeZone timezone) {
+
+    this.axisPair.xAxis.axisTick.timezone = timezone;
+    this.axisPair.yAxis.axisTick.timezone = timezone;
+  }
+
 }
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java
index dd2f5a2c..69689e57 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java
@@ -21,6 +21,7 @@ import java.math.BigDecimal;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
+import java.util.TimeZone;
 
 import com.xeiam.xchart.internal.chartpart.Axis.AxisType;
 import com.xeiam.xchart.internal.chartpart.Axis.Direction;
@@ -59,9 +60,12 @@ public class AxisTick implements IChartPart, IHideable {
 
   private int workingSpace;
 
-  /** the Locale for Date tick labels */
+  /** the Locale for tick labels */
   public Locale locale;
 
+  /** the TimeZone for Date tick labels */
+  public TimeZone timezone;
+
   public String normalDecimalPattern = null;
   public String scientificDecimalPattern = null;
   public String datePattern = null;
@@ -254,7 +258,7 @@ public class AxisTick implements IChartPart, IHideable {
 
     } else {
 
-      return AxisValueFormatterUtil.formatDateValue(value, axis.min, axis.max, datePattern, locale);
+      return AxisValueFormatterUtil.formatDateValue(value, axis.min, axis.max, datePattern, locale, timezone);
     }
 
   }
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/misc/AxisValueFormatterUtil.java b/xchart/src/main/java/com/xeiam/xchart/internal/misc/AxisValueFormatterUtil.java
index 1a6c184a..554adf9f 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/misc/AxisValueFormatterUtil.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/misc/AxisValueFormatterUtil.java
@@ -26,6 +26,8 @@ import java.text.DecimalFormat;
 import java.text.NumberFormat;
 import java.text.SimpleDateFormat;
 import java.util.Locale;
+import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @author timmolter
@@ -36,14 +38,15 @@ public class AxisValueFormatterUtil {
   private static final String SCIENTIFIC_DECIMAL_PATTERN = "0.##E0";
   private static final String DATE_PATTERN = "HHmmss";
   private static final Locale LOCALE = Locale.getDefault();
+  private static final TimeZone TIMEZONE = TimeZone.getDefault();
 
-  private static final BigDecimal SEC_SCALE = new BigDecimal(1000L);
-  private static final BigDecimal MIN_SCALE = new BigDecimal(1000L * 60);
-  private static final BigDecimal HOUR_SCALE = new BigDecimal(1000L * 60 * 60);
-  private static final BigDecimal DAY_SCALE = new BigDecimal(1000L * 60 * 60 * 24);
-  private static final BigDecimal WEEK_SCALE = new BigDecimal(1000L * 60 * 60 * 24 * 7);
-  private static final BigDecimal MONTH_SCALE = new BigDecimal(1000L * 60 * 60 * 24 * 31);
-  private static final BigDecimal YEAR_SCALE = new BigDecimal(1000L * 60 * 60 * 24 * 365);
+  private static final long SEC_SCALE = TimeUnit.SECONDS.toMillis(1L);
+  private static final long MIN_SCALE = TimeUnit.MINUTES.toMillis(1L);
+  private static final long HOUR_SCALE = TimeUnit.HOURS.toMillis(1L);
+  private static final long DAY_SCALE = TimeUnit.DAYS.toMillis(1L);
+  private static final long WEEK_SCALE = TimeUnit.DAYS.toMillis(1L) * 7;
+  private static final long MONTH_SCALE = TimeUnit.DAYS.toMillis(1L) * 31;
+  private static final long YEAR_SCALE = TimeUnit.DAYS.toMillis(1L) * 365;
 
   /**
    * Constructor
@@ -93,27 +96,27 @@ public class AxisValueFormatterUtil {
    * @param localeOverride
    * @return the formatted date value as a String
    */
-  public static String formatDateValue(BigDecimal value, BigDecimal min, BigDecimal max, String datePatternOverride, Locale localeOverride) {
+  public static String formatDateValue(BigDecimal value, BigDecimal min, BigDecimal max, String datePatternOverride, Locale localeOverride, TimeZone timeZoneOverride) {
 
     // intelligently set datepattern if none is given
     String datePattern = datePatternOverride;
     if (datePatternOverride == null) {
       datePattern = DATE_PATTERN;
-      BigDecimal diff = max.subtract(min);
+      long diff = max.subtract(min).longValue();
 
-      if (diff.compareTo(SEC_SCALE) == -1) {
+      if (diff < SEC_SCALE) {
         datePattern = "ss:S";
-      } else if (diff.compareTo(MIN_SCALE) == -1) {
+      } else if (diff < MIN_SCALE) {
         datePattern = "mm:ss";
-      } else if (diff.compareTo(HOUR_SCALE) == -1) {
+      } else if (diff < HOUR_SCALE) {
         datePattern = "HH:mm";
-      } else if (diff.compareTo(DAY_SCALE) == -1) {
-        datePattern = "dd:HH";
-      } else if (diff.compareTo(WEEK_SCALE) == -1) {
+      } else if (diff < DAY_SCALE) {
+        datePattern = "EEE HH:mm";
+      } else if (diff < WEEK_SCALE) {
         datePattern = "EEE";
-      } else if (diff.compareTo(MONTH_SCALE) == -1) {
+      } else if (diff < MONTH_SCALE) {
         datePattern = "MMM-dd";
-      } else if (diff.compareTo(YEAR_SCALE) == -1) {
+      } else if (diff < YEAR_SCALE) {
         datePattern = "yyyy:MMM";
       } else {
         datePattern = "yyyy";
@@ -122,9 +125,9 @@ public class AxisValueFormatterUtil {
     }
 
     SimpleDateFormat simpleDateformat = new SimpleDateFormat(datePattern, localeOverride == null ? LOCALE : localeOverride);
+    simpleDateformat.setTimeZone(timeZoneOverride == null ? TIMEZONE : timeZoneOverride);
     simpleDateformat.applyPattern(datePattern);
     return simpleDateformat.format(value.longValueExact());
 
   }
-
 }
diff --git a/xchart/src/test/java/com/xeiam/xchart/ValueFormatTest.java b/xchart/src/test/java/com/xeiam/xchart/ValueFormatTest.java
index c8a99093..b1919546 100644
--- a/xchart/src/test/java/com/xeiam/xchart/ValueFormatTest.java
+++ b/xchart/src/test/java/com/xeiam/xchart/ValueFormatTest.java
@@ -26,6 +26,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
 
 import java.math.BigDecimal;
 import java.util.Locale;
+import java.util.TimeZone;
 
 import org.junit.Test;
 
@@ -36,9 +37,6 @@ import com.xeiam.xchart.internal.misc.AxisValueFormatterUtil;
  */
 public class ValueFormatTest {
 
-  // private final String normalDecimalPattern = "#.####";
-  // private final String scientificDecimalPattern = "0.##E0";
-  // private final String datePattern = "HHmmss";
   private final Locale locale = Locale.US;
 
   @Test
@@ -115,61 +113,62 @@ public class ValueFormatTest {
   @Test
   public void testDateFormatting() {
 
+    TimeZone timeZone = TimeZone.getTimeZone("UTC");
+
     // ms
     BigDecimal value = new BigDecimal(1358108105531L);
     BigDecimal min = new BigDecimal(1358108105100L);
     BigDecimal max = new BigDecimal(1358108105900L);
-    String stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale);
+    String stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale, timeZone);
     assertThat(stringValue, equalTo("05:531"));
 
     // sec
     value = new BigDecimal(1358108105000L);
     min = new BigDecimal(1358108101000L);
     max = new BigDecimal(1358108109000L);
-    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale);
+    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale, timeZone);
     assertThat(stringValue, equalTo("15:05"));
 
-    // TODO this fails on a server in a different timezone. how to fix?
-    // // min
-    // value = new BigDecimal(1358111750000L);
-    // min = new BigDecimal(1358111690000L);
-    // max = new BigDecimal(1358111870000L);
-    // stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale);
-    // assertThat(stringValue, equalTo("22:15"));
-    //
-    // // hour
-    // value = new BigDecimal(1358111870000L);
-    // min = new BigDecimal(1358101070000L);
-    // max = new BigDecimal(1358115470000L);
-    // stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale);
-    // assertThat(stringValue, equalTo("13:22"));
+    // min
+    value = new BigDecimal(1358111750000L);
+    min = new BigDecimal(1358111690000L);
+    max = new BigDecimal(1358111870000L);
+    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale, timeZone);
+    assertThat(stringValue, equalTo("21:15"));
+
+    // hour
+    value = new BigDecimal(1358111870000L);
+    min = new BigDecimal(1358101070000L);
+    max = new BigDecimal(1358115470000L);
+    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale, timeZone);
+    assertThat(stringValue, equalTo("Sun 21:17"));
 
     // day
     value = new BigDecimal(1358112317000L);
     min = new BigDecimal(1357939517000L);
     max = new BigDecimal(1358285117000L);
-    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale);
+    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale, timeZone);
     assertThat(stringValue, equalTo("Sun"));
 
     // week
     value = new BigDecimal(1358112317000L);
     min = new BigDecimal(1357075517000L);
     max = new BigDecimal(1359149117000L);
-    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale);
+    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale, timeZone);
     assertThat(stringValue, equalTo("Jan-13"));
 
     // month
     value = new BigDecimal(1358112838000L);
     min = new BigDecimal(1354397638000L);
     max = new BigDecimal(1361223238000L);
-    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale);
+    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale, timeZone);
     assertThat(stringValue, equalTo("2013:Jan"));
 
     // year
     value = new BigDecimal(1358113402000L);
     min = new BigDecimal(1263419002000L);
     max = new BigDecimal(1421185402000L);
-    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale);
+    stringValue = AxisValueFormatterUtil.formatDateValue(value, min, max, null, locale, timeZone);
     assertThat(stringValue, equalTo("2013"));
 
   }
-- 
GitLab