Example usage for org.jfree.data.time Day getFirstMillisecond

List of usage examples for org.jfree.data.time Day getFirstMillisecond

Introduction

In this page you can find the example usage for org.jfree.data.time Day getFirstMillisecond.

Prototype

@Override
public long getFirstMillisecond() 

Source Link

Document

Returns the first millisecond of the day.

Usage

From source file:org.sonar.server.charts.jruby.TrendsChart.java

public void addLabel(Date date, String label, boolean lower) throws ParseException {
    Day d = new Day(date);
    double millis = d.getFirstMillisecond();
    Marker marker = new ValueMarker(millis);
    marker.setLabel(label);//  w ww.j  a va2 s.  c o  m
    marker.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
    marker.setLabelTextAnchor(TextAnchor.TOP_LEFT);
    Color c = new Color(17, 40, 95);
    marker.setLabelPaint(c);
    marker.setPaint(c);
    marker.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 3.0f,
            new float[] { 5f, 5f, 5f, 5f }, 2.0f));
    if (lower) {
        marker.setLabelOffset(new RectangleInsets(18, 0, 0, 5));
    }
    plot.addDomainMarker(marker);
}

From source file:org.jfree.data.time.DayTest.java

/**
 * Some checks for the getFirstMillisecond() method.
 *///  w  w w.ja  v  a2s  .  c  o  m
@Test
public void testGetFirstMillisecond() {
    Locale saved = Locale.getDefault();
    Locale.setDefault(Locale.UK);
    TimeZone savedZone = TimeZone.getDefault();
    TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
    Day d = new Day(1, 3, 1970);
    assertEquals(5094000000L, d.getFirstMillisecond());
    Locale.setDefault(saved);
    TimeZone.setDefault(savedZone);
}

From source file:org.jrecruiter.web.actions.admin.ShowStatisticsAction.java

public final String chartJobCount() throws Exception {

    final Calendar calendarToday = CalendarUtils.getCalendarWithoutTime();

    final Calendar calendar30 = CalendarUtils.getCalendarWithoutTime();
    calendar30.add(Calendar.MONTH, -36);

    final List<JobCountPerDay> jobCountPerDayList = jobService.getJobCountPerDayAndPeriod(calendar30.getTime(),
            calendarToday.getTime());/* ww w  . ja v a 2 s  .c  o  m*/

    final TimeSeries hitsPerDayData = new TimeSeries("Hits", Day.class);
    final XYDataset hitsPerDayDataset = new TimeSeriesCollection(hitsPerDayData);
    this.chart = ChartFactory.createTimeSeriesChart("",
            super.getText("class.ShowStatisticsAcion.chart.job.count.caption"), "", hitsPerDayDataset, false,
            true, false);

    final XYPlot xyplot = (XYPlot) this.chart.getPlot();

    for (JobCountPerDay jobCountPerDay : jobCountPerDayList) {

        final Day day = new Day(jobCountPerDay.getJobDate());

        if (jobCountPerDay.getAutomaticallyCleaned()) {

            final Marker originalEnd = new ValueMarker(day.getFirstMillisecond());
            originalEnd.setPaint(new Color(0, 80, 138, 150));
            float[] dashPattern = { 6, 2 };

            originalEnd.setStroke(
                    new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10, dashPattern, 0));
            originalEnd.setLabelAnchor(RectangleAnchor.TOP_LEFT);
            originalEnd.setLabelTextAnchor(TextAnchor.TOP_RIGHT);
            originalEnd.setLabel("C");
            originalEnd.setAlpha(0.1F);
            xyplot.addDomainMarker(originalEnd);
        }

        hitsPerDayData.add(day, jobCountPerDay.getTotalNumberOfJobs());
    }

    chart.setBackgroundPaint(new Color(255, 255, 255, 0));

    xyplot.setDomainGridlinePaint(Color.LIGHT_GRAY);
    xyplot.setBackgroundPaint(new Color(255, 255, 255, 0));

    xyplot.setRangeGridlinePaint(Color.LIGHT_GRAY);
    xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
    xyplot.setDomainCrosshairVisible(true);
    xyplot.setRangeCrosshairVisible(true);

    org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
    if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
        XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
        xylineandshaperenderer.setBaseShapesVisible(false);
        xyitemrenderer.setSeriesPaint(0, new Color(244, 66, 0));
    }

    DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();

    dateaxis.setAutoRange(true);
    dateaxis.setAutoTickUnitSelection(true);

    NumberAxis valueAxis = (NumberAxis) xyplot.getRangeAxis();
    valueAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

    return SUCCESS;
}

From source file:org.jfree.data.time.junit.DayTest.java

/**
 * Some checks for the getFirstMillisecond() method.
 *///w w w . ja va  2 s  .c o  m
public void testGetFirstMillisecond() {
    Locale saved = Locale.getDefault();
    Locale.setDefault(Locale.UK);
    TimeZone savedZone = TimeZone.getDefault();
    TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
    Day d = new Day(1, 3, 1970);
    assertEquals(5094000000L, d.getFirstMillisecond());
    Locale.setDefault(saved);
    TimeZone.setDefault(savedZone);
}

From source file:org.jfree.data.time.TimeSeriesCollectionTest.java

/**
 * Test the getSurroundingItems() method to ensure it is returning the
 * values we expect./*  w  w  w .jav a2 s.  co m*/
 */
@Test
public void testGetSurroundingItems() {
    TimeSeries series = new TimeSeries("Series 1");
    TimeSeriesCollection collection = new TimeSeriesCollection(series);
    collection.setXPosition(TimePeriodAnchor.MIDDLE);

    // for a series with no data, we expect {-1, -1}...
    int[] result = collection.getSurroundingItems(0, 1000L);
    assertTrue(result[0] == -1);
    assertTrue(result[1] == -1);

    // now test with a single value in the series...
    Day today = new Day();
    long start1 = today.getFirstMillisecond();
    long middle1 = today.getMiddleMillisecond();
    long end1 = today.getLastMillisecond();

    series.add(today, 99.9);
    result = collection.getSurroundingItems(0, start1);
    assertTrue(result[0] == -1);
    assertTrue(result[1] == 0);

    result = collection.getSurroundingItems(0, middle1);
    assertTrue(result[0] == 0);
    assertTrue(result[1] == 0);

    result = collection.getSurroundingItems(0, end1);
    assertTrue(result[0] == 0);
    assertTrue(result[1] == -1);

    // now add a second value to the series...
    Day tomorrow = (Day) today.next();
    long start2 = tomorrow.getFirstMillisecond();
    long middle2 = tomorrow.getMiddleMillisecond();
    long end2 = tomorrow.getLastMillisecond();

    series.add(tomorrow, 199.9);
    result = collection.getSurroundingItems(0, start2);
    assertTrue(result[0] == 0);
    assertTrue(result[1] == 1);

    result = collection.getSurroundingItems(0, middle2);
    assertTrue(result[0] == 1);
    assertTrue(result[1] == 1);

    result = collection.getSurroundingItems(0, end2);
    assertTrue(result[0] == 1);
    assertTrue(result[1] == -1);

    // now add a third value to the series...
    Day yesterday = (Day) today.previous();
    long start3 = yesterday.getFirstMillisecond();
    long middle3 = yesterday.getMiddleMillisecond();
    long end3 = yesterday.getLastMillisecond();

    series.add(yesterday, 1.23);
    result = collection.getSurroundingItems(0, start3);
    assertTrue(result[0] == -1);
    assertTrue(result[1] == 0);

    result = collection.getSurroundingItems(0, middle3);
    assertTrue(result[0] == 0);
    assertTrue(result[1] == 0);

    result = collection.getSurroundingItems(0, end3);
    assertTrue(result[0] == 0);
    assertTrue(result[1] == 1);
}

From source file:org.yccheok.jstock.gui.charting.ChartLayerUI.java

private boolean updateMainTraceInfo(Point2D point) {
    if (point == null) {
        return false;
    }//from w w w  .j av a 2 s .  c o m

    final ChartPanel chartPanel = this.chartJDialog.getChartPanel();
    // Top most plot.
    final XYPlot plot = this.chartJDialog.getPlot();

    if (plot.getDataset() instanceof org.jfree.data.xy.DefaultHighLowDataset) {
        return this._updateMainTraceInfoForCandlestick(point);
    }

    final TimeSeriesCollection timeSeriesCollection = (TimeSeriesCollection) plot.getDataset();
    // 0 are the main chart. 1, 2, 3... are TA.
    final TimeSeries timeSeries = timeSeriesCollection.getSeries(0);

    // I also not sure why. This is what are being done in Mouse Listener Demo 4.
    //
    // Don't use it. It will cause us to lose precision.
    //final Point2D p2 = chartPanel.translateScreenToJava2D((Point)point);

    /* Try to get correct main chart area. */
    final Rectangle2D _plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0)
            .getDataArea();

    final ValueAxis domainAxis = plot.getDomainAxis();
    final RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
    final ValueAxis rangeAxis = plot.getRangeAxis();
    final RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
    // Don't use it. It will cause us to lose precision.
    //final double coordinateX = domainAxis.java2DToValue(p2.getX(), _plotArea,
    //        domainAxisEdge);
    final double coordinateX = domainAxis.java2DToValue(point.getX(), _plotArea, domainAxisEdge);
    //double coordinateY = rangeAxis.java2DToValue(mousePoint2.getY(), plotArea,
    //        rangeAxisEdge);

    int low = 0;
    int high = timeSeries.getItemCount() - 1;
    Date date = new Date((long) coordinateX);
    final long time = date.getTime();
    long bestDistance = Long.MAX_VALUE;
    int bestMid = 0;

    while (low <= high) {
        int mid = (low + high) >>> 1;

        final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(mid);
        final Day day = (Day) timeSeriesDataItem.getPeriod();
        final long search = day.getFirstMillisecond();
        final long cmp = search - time;

        if (cmp < 0) {
            low = mid + 1;
        } else if (cmp > 0) {
            high = mid - 1;
        } else {
            bestDistance = 0;
            bestMid = mid;
            break;
        }

        final long abs_cmp = Math.abs(cmp);
        if (abs_cmp < bestDistance) {
            bestDistance = abs_cmp;
            bestMid = mid;
        }
    }

    final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(bestMid);
    final double xValue = timeSeriesDataItem.getPeriod().getFirstMillisecond();
    final double yValue = timeSeriesDataItem.getValue().doubleValue();
    final double xJava2D = domainAxis.valueToJava2D(xValue, _plotArea, domainAxisEdge);
    final double yJava2D = rangeAxis.valueToJava2D(yValue, _plotArea, rangeAxisEdge);

    final int tmpIndex = bestMid;
    // translateJava2DToScreen will internally convert Point2D.Double to Point.
    final Point2D tmpPoint = chartPanel.translateJava2DToScreen(new Point2D.Double(xJava2D, yJava2D));
    this.mainDrawArea.setRect(_plotArea);

    if (this.mainDrawArea.contains(tmpPoint)) {
        // 0 indicates main plot.
        this.mainTraceInfo = TraceInfo.newInstance(tmpPoint, 0, 0, tmpIndex);
        return true;
    }
    return false;
}

From source file:org.yccheok.jstock.gui.charting.InvestmentFlowLayerUI.java

private boolean updateInvestPoint(Point2D _investPoint) {
    if (_investPoint == null) {
        return false;
    }//from   ww w  . j  av a 2 s  . co m

    final ChartPanel chartPanel = this.investmentFlowChartJDialog.getChartPanel();
    final JFreeChart chart = chartPanel.getChart();
    final XYPlot plot = (XYPlot) chart.getPlot();
    final TimeSeriesCollection timeSeriesCollection = (TimeSeriesCollection) plot.getDataset();
    final TimeSeries timeSeries = timeSeriesCollection.getSeries(0);

    // I also not sure why. This is what are being done in Mouse Listener Demo 4.
    //
    // Don't use it. It will cause us to lose precision.
    //final Point2D p2 = chartPanel.translateScreenToJava2D((Point)_investPoint);

    /* Try to get correct main chart area. */
    final Rectangle2D _plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();

    /* Believe it? When there is another thread keep updateing time series data,
     * and keep calling setDirty, _plotArea can be 0 size sometimes. Ignore it.
     * Just assume we had processed it.
     */
    if (_plotArea.getWidth() == 0.0 && _plotArea.getHeight() == 0.0) {
        /* Cheat the caller. */
        return true;
    }

    final ValueAxis domainAxis = plot.getDomainAxis();
    final RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
    final ValueAxis rangeAxis = plot.getRangeAxis();
    final RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
    final double coordinateX = domainAxis.java2DToValue(_investPoint.getX(), _plotArea, domainAxisEdge);

    int low = 0;
    int high = timeSeries.getItemCount() - 1;
    Date date = new Date((long) coordinateX);
    final long time = date.getTime();
    long bestDistance = Long.MAX_VALUE;
    int bestMid = 0;

    while (low <= high) {
        int mid = (low + high) >>> 1;

        final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(mid);
        final Day day = (Day) timeSeriesDataItem.getPeriod();
        final long search = day.getFirstMillisecond();
        final long cmp = search - time;

        if (cmp < 0) {
            low = mid + 1;
        } else if (cmp > 0) {
            high = mid - 1;
        } else {
            bestDistance = 0;
            bestMid = mid;
            break;
        }

        final long abs_cmp = Math.abs(cmp);
        if (abs_cmp < bestDistance) {
            bestDistance = abs_cmp;
            bestMid = mid;
        }
    }

    final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(bestMid);
    final double xValue = timeSeriesDataItem.getPeriod().getFirstMillisecond();
    final double yValue = timeSeriesDataItem.getValue().doubleValue();
    final double xJava2D = domainAxis.valueToJava2D(xValue, _plotArea, domainAxisEdge);
    final double yJava2D = rangeAxis.valueToJava2D(yValue, _plotArea, rangeAxisEdge);

    final int tmpIndex = bestMid;
    // Do not perform translation as this will cause precision losing.
    // We might experience unstable point. For example,
    //
    // this.investPoint is 700.9, there are 2 data points which are 700 and
    // 701.
    // During first updateInvestPoint(this.investPoint) call, data point 701
    // will be chosen, and this.investPoint has been truncated to 700.
    // During second updateInvestPoint(this.investPoint) call, data point 700
    // will be chosen. We may observe an unstable point swings between 700
    // and 701.
    //
    // translateJava2DToScreen will internally convert Point2D.Double to Point.
    //final Point2D tmpPoint = chartPanel.translateJava2DToScreen(new Point2D.Double(xJava2D, yJava2D));
    final Point2D tmpPoint = new Point2D.Double(xJava2D, yJava2D);
    this.drawArea.setRect(_plotArea);

    if (this.drawArea.contains(tmpPoint)) {
        this.investPointIndex = tmpIndex;
        this.investPoint = tmpPoint;
        return true;
    }
    return false;
}

From source file:org.yccheok.jstock.gui.charting.InvestmentFlowLayerUI.java

private boolean updateROIPoint(Point2D _ROIPoint) {
    if (_ROIPoint == null) {
        return false;
    }/*from   w  w w  . j av  a  2s  .  c  o m*/

    final ChartPanel chartPanel = this.investmentFlowChartJDialog.getChartPanel();
    final JFreeChart chart = chartPanel.getChart();
    final XYPlot plot = (XYPlot) chart.getPlot();
    // Dataset 0 are the invest information. 1 is the ROI information.
    final TimeSeriesCollection timeSeriesCollection = (TimeSeriesCollection) plot.getDataset(1);
    final TimeSeries timeSeries = timeSeriesCollection.getSeries(0);

    // I also not sure why. This is what are being done in Mouse Listener Demo 4.
    //
    // Don't use it. It will cause us to lose precision.
    //final Point2D p2 = chartPanel.translateScreenToJava2D((Point)_ROIPoint);

    /* Try to get correct main chart area. */
    final Rectangle2D _plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();

    /* Believe it? When there is another thread keep updateing time series data,
     * and keep calling setDirty, _plotArea can be 0 size sometimes. Ignore it.
     * Just assume we had processed it.
     */
    if (_plotArea.getWidth() == 0.0 && _plotArea.getHeight() == 0.0) {
        /* Cheat the caller. */
        return true;
    }

    final ValueAxis domainAxis = plot.getDomainAxis();
    final RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
    final ValueAxis rangeAxis = plot.getRangeAxis();
    final RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
    final double coordinateX = domainAxis.java2DToValue(_ROIPoint.getX(), _plotArea, domainAxisEdge);

    int low = 0;
    int high = timeSeries.getItemCount() - 1;
    Date date = new Date((long) coordinateX);
    final long time = date.getTime();
    long bestDistance = Long.MAX_VALUE;
    int bestMid = 0;

    while (low <= high) {
        int mid = (low + high) >>> 1;

        final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(mid);
        final Day day = (Day) timeSeriesDataItem.getPeriod();
        final long search = day.getFirstMillisecond();
        final long cmp = search - time;

        if (cmp < 0) {
            low = mid + 1;
        } else if (cmp > 0) {
            high = mid - 1;
        } else {
            bestDistance = 0;
            bestMid = mid;
            break;
        }

        final long abs_cmp = Math.abs(cmp);
        if (abs_cmp < bestDistance) {
            bestDistance = abs_cmp;
            bestMid = mid;
        }
    }

    final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(bestMid);
    final double xValue = timeSeriesDataItem.getPeriod().getFirstMillisecond();
    final double yValue = timeSeriesDataItem.getValue().doubleValue();
    final double xJava2D = domainAxis.valueToJava2D(xValue, _plotArea, domainAxisEdge);
    final double yJava2D = rangeAxis.valueToJava2D(yValue, _plotArea, rangeAxisEdge);

    final int tmpIndex = bestMid;
    // Do not perform translation as this will cause precision losing.
    // We might experience unstable point. For example,
    //
    // this.ROIPoint is 700.9, there are 2 data points which are 700 and
    // 701.
    // During first updateROIPoint(this.ROIPoint) call, data point 701
    // will be chosen, and this.ROIPoint has been truncated to 700.
    // During second updateROIPoint(this.ROIPoint) call, data point 700
    // will be chosen. We may observe an unstable point swings between 700
    // and 701.
    //
    // translateJava2DToScreen will internally convert Point2D.Double to Point.
    //final Point2D tmpPoint = chartPanel.translateJava2DToScreen(new Point2D.Double(xJava2D, yJava2D));
    final Point2D tmpPoint = new Point2D.Double(xJava2D, yJava2D);
    this.drawArea.setRect(_plotArea);

    if (this.drawArea.contains(tmpPoint)) {
        this.ROIPointIndex = tmpIndex;
        this.ROIPoint = tmpPoint;
        return true;
    }
    return false;
}

From source file:org.yccheok.jstock.gui.charting.ChartJDialog.java

/**
 * Calculate and update high low value labels, according to current displayed
 * time range. This is a time consuming method, and shall be called by
 * user thread.//from   w w  w  . j  a  v a  2s.c om
 */
private void _updateHighLowJLabels() {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            ChartJDialog.this.jLabel2.setText("");
            ChartJDialog.this.jLabel4.setText("");
        }
    });

    final ValueAxis valueAxis = this.getPlot().getDomainAxis();
    final Range range = valueAxis.getRange();
    final long lowerBound = (long) range.getLowerBound();
    final long upperBound = (long) range.getUpperBound();

    // Perform binary search, to located day in price time series, which
    // is equal or lesser than upperBound.
    int low = 0;
    int high = this.priceTimeSeries.getItemCount() - 1;
    long best_dist = Long.MAX_VALUE;
    int best_mid = -1;
    while (low <= high) {
        int mid = (low + high) >>> 1;
        final Day day = (Day) this.priceTimeSeries.getDataItem(mid).getPeriod();
        long v = day.getFirstMillisecond();

        if (v > upperBound) {
            high = mid - 1;
        } else if (v < upperBound) {
            low = mid + 1;
            long dist = upperBound - v;
            if (dist < best_dist) {
                best_dist = dist;
                best_mid = mid;
            }
        } else {
            best_dist = 0;
            best_mid = mid;
            break;
        }
    }

    if (best_mid < 0) {
        return;
    }

    double high_price = -Double.MAX_VALUE;
    double low_price = Double.MAX_VALUE;
    final DefaultHighLowDataset defaultHighLowDataset = (DefaultHighLowDataset) this.priceOHLCDataset;
    for (int i = best_mid; i >= 0; i--) {
        final TimeSeriesDataItem item = this.priceTimeSeries.getDataItem(i);
        final long time = ((Day) item.getPeriod()).getFirstMillisecond();
        if (time < lowerBound) {
            break;
        }

        final double _high_price = defaultHighLowDataset.getHighValue(0, i);
        final double _low_price = defaultHighLowDataset.getLowValue(0, i);
        final double _last_price = defaultHighLowDataset.getCloseValue(0, i);

        high_price = Math.max(high_price, _high_price);

        // Prevent bad data.
        if (_low_price > 0) {
            low_price = Math.min(low_price, _low_price);
        } else {
            if (_high_price > 0) {
                low_price = Math.min(low_price, _high_price);
            }
            if (_last_price > 0) {
                low_price = Math.min(low_price, _last_price);
            }
        }
    }

    final double h = high_price;
    final double l = low_price;
    if (high_price >= low_price) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                ChartJDialog.this.jLabel2.setText(org.yccheok.jstock.gui.Utils.stockPriceDecimalFormat(h));
                ChartJDialog.this.jLabel4.setText(org.yccheok.jstock.gui.Utils.stockPriceDecimalFormat(l));
            }
        });
    }
}

From source file:org.yccheok.jstock.gui.charting.ChartJDialog.java

/**
 * Zoom in to this chart with specific amount of time.
 * @param field the calendar field./*from   www  .  ja  v  a 2 s. c  om*/
 * @param amount the amount of date or time to be added to the field.
 */
private void _zoom(int field, int amount) {
    this.chartPanel.restoreAutoBounds();

    final int itemCount = this.priceTimeSeries.getItemCount();
    final Day day = (Day) this.priceTimeSeries.getDataItem(itemCount - 1).getPeriod();
    // Candle stick takes up half day space.
    // Volume price chart's volume information takes up whole day space.
    final long end = day.getFirstMillisecond()
            + (this.getCurrentType() == Type.Candlestick ? (1000 * 60 * 60 * 12) : (1000 * 60 * 60 * 24 - 1));
    final Calendar calendar = Calendar.getInstance();
    // -1. Calendar's month is 0 based but JFreeChart's month is 1 based.
    calendar.set(day.getYear(), day.getMonth() - 1, day.getDayOfMonth(), 0, 0, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    calendar.add(field, amount);
    // Candle stick takes up half day space.
    // Volume price chart's volume information does not take up any space.
    final long start = Math.max(0, calendar.getTimeInMillis()
            - (this.getCurrentType() == Type.Candlestick ? (1000 * 60 * 60 * 12) : 0));
    final ValueAxis valueAxis = this.getPlot().getDomainAxis();

    if (priceTimeSeries.getItemCount() > 0) {
        if (start < priceTimeSeries.getTimePeriod(0).getFirstMillisecond()) {
            // To prevent zoom-out too much.
            // This happens when user demands for 10 years zoom, where we
            // are only having 5 years data.
            return;
        }
    }

    valueAxis.setRange(start, end);

    double min = Double.MAX_VALUE;
    double max = Double.MIN_VALUE;
    double max_volume = Double.MIN_VALUE;
    final DefaultHighLowDataset defaultHighLowDataset = (DefaultHighLowDataset) this.priceOHLCDataset;

    for (int i = itemCount - 1; i >= 0; i--) {
        final TimeSeriesDataItem item = this.priceTimeSeries.getDataItem(i);
        final Day d = (Day) item.getPeriod();
        if (d.getFirstMillisecond() < start) {
            break;
        }

        final double high = defaultHighLowDataset.getHighValue(0, i);
        final double low = defaultHighLowDataset.getLowValue(0, i);
        final double volume = defaultHighLowDataset.getVolumeValue(0, i);

        if (max < high) {
            max = high;
        }
        if (min > low) {
            min = low;
        }
        if (max_volume < volume) {
            max_volume = volume;
        }
    }

    if (min > max) {
        return;
    }

    final ValueAxis rangeAxis = this.getPlot().getRangeAxis();
    final Range rangeAxisRange = rangeAxis.getRange();
    // Increase each side by 1%
    double tolerance = 0.01 * (max - min);
    // The tolerance must within range [0.01, 1.0]
    tolerance = Math.min(Math.max(0.01, tolerance), 1.0);
    // The range must within the original chart range.
    min = Math.max(rangeAxisRange.getLowerBound(), min - tolerance);
    max = Math.min(rangeAxisRange.getUpperBound(), max + tolerance);

    this.getPlot().getRangeAxis().setRange(min, max);

    if (this.getPlot().getRangeAxisCount() > 1) {
        final double volumeUpperBound = this.getPlot().getRangeAxis(1).getRange().getUpperBound();
        final double suggestedVolumneUpperBound = max_volume * 4;
        // To prevent over zoom-in.
        if (suggestedVolumneUpperBound < volumeUpperBound) {
            this.getPlot().getRangeAxis(1).setRange(0, suggestedVolumneUpperBound);
        }
    }
}