vasu_murthy Posted December 6, 2008 Share Posted December 6, 2008 Hi, I am using time series charts in iReports designer 3.0.0 to display time in X-axis , count of rows in Y-axis and Series expression to show in various colors. The issue i am facing is that, if i query the database for 3 days time period and it returns quite a number of rows as follows: Day 1 -- 3 rows Day 2 -- 0 rows Day 3 -- 5 rows The line drawn by the time Series chart now directly plots from Day 1 to Day 3, i.e., from value 3 to 5 in Y-axis. Ideally the line should start at point 3 on Day 1, touch zero on Day 2 and then reach 5 on Day 3. But the way currently the time Series chart behaves is, zero points are ignored in between two non-zero points. In my example it should touch zero point on Day 2 even though my query did not return any rows on that day. The way the time Series chart plot now joins Day 1 value (3) with Day 3 value (5) and it gives a false impression that Day 2 Y-axis value might be 4, which should have been zero. Please let me know if you faced this kind of scenario and do I need to provide any more details on the issue. Thanks Vasu Link to comment Share on other sites More sharing options...
rreganjr Posted January 15, 2010 Share Posted January 15, 2010 I think the problem isn't that day 2 has a value of 0, its day 2 has no entry, I had a similar problem drawing a chart of sparse data. The only solution I found was using a JRChartCustomizer to add the missing periods with a zero value. Code:package utils;import java.util.Date;import org.jfree.chart.JFreeChart;import org.jfree.chart.plot.XYPlot;import org.jfree.data.time.Day;import org.jfree.data.time.Hour;import org.jfree.data.time.Minute;import org.jfree.data.time.Month;import org.jfree.data.time.Second;import org.jfree.data.time.TimeSeries;import org.jfree.data.time.TimeSeriesCollection;import org.jfree.data.time.Week;import org.jfree.data.time.Year;import net.sf.jasperreports.engine.JRAbstractChartCustomizer;import net.sf.jasperreports.engine.JRChart;/** * This is a Jasper Reports chart customizer for time series chart that will fill in * missing time periods in the dataset with 0 value entries. For example if your plotting * the number of hits to a website by hour and there were 10 hits at midnight and 10 hits * at 6 am, but no hits from 1 am to 5 am by default the time series chart will draw a strait * line from the midnight plot point to the 6 am plot point, if you want the line to drop to * zero this class can be set in the chart element customizerClass attribute and Jasper Reports * will call it before generating the chart. * * NOTE: this has dependencies on the jrxml file that a startDateInternal and endDateInternal * property exists that holds the start and end date to be plotted. * * @author ron@nellymoser.com * */public class JRTimeSeriesCustomizerEmptyDateFiller extends JRAbstractChartCustomizer { public void customize(JFreeChart chart, JRChart jasperChart) { Date startDate = (Date) getParameterValue("startDateInternal", true); Date endDate = (Date) getParameterValue("endDateInternal", true); if (chart.getPlot() != null && chart.getPlot() instanceof XYPlot) { XYPlot plot = (XYPlot) chart.getPlot(); for (int i = 0; i < plot.getDatasetCount(); i++) { Object genericDataSet = plot.getDataset(i); if (genericDataSet != null && genericDataSet instanceof TimeSeriesCollection) { TimeSeriesCollection tsc = (TimeSeriesCollection) genericDataSet; for (Object genericTimeSeries : tsc.getSeries()) { if (genericTimeSeries != null && genericTimeSeries instanceof TimeSeries) { TimeSeries timeSeries = (TimeSeries) genericTimeSeries; fillInMissingPeriods(timeSeries, startDate, endDate, timeSeries.getTimePeriodClass()); } } } } } } // TODO: it would be more effecient to move the while inside each if statement so the if is only executed // once instead of each period from start to end. private void fillInMissingPeriods(TimeSeries timeSeries, Date startDate, Date endDate, Class<?> period) { Date dateIndex = startDate; while (dateIndex.before(endDate)) { if (Day.class.equals(period)) { dateIndex = DateUtils.startOfDay(dateIndex); if (timeSeries.getDataItem(new Day(dateIndex)) == null) { timeSeries.add(new Day(dateIndex), 0.0d); } dateIndex = DateUtils.addDays(dateIndex, 1); } else if (Hour.class.equals(period)) { dateIndex = DateUtils.startOfHour(dateIndex); if (timeSeries.getDataItem(new Hour(dateIndex)) == null) { timeSeries.add(new Hour(dateIndex), 0.0d); } dateIndex = DateUtils.addHours(dateIndex, 1); } else if (Minute.class.equals(period)) { dateIndex = DateUtils.startOfMinute(dateIndex); if (timeSeries.getDataItem(new Minute(dateIndex)) == null) { timeSeries.add(new Minute(dateIndex), 0.0d); } dateIndex = DateUtils.addMinutes(dateIndex, 1); } else if (Second.class.equals(period)) { dateIndex = DateUtils.startOfSecond(dateIndex); if (timeSeries.getDataItem(new Second(dateIndex)) == null) { timeSeries.add(new Second(dateIndex), 0.0d); } dateIndex = DateUtils.addSeconds(dateIndex, 1); } else if (Week.class.equals(period)) { dateIndex = DateUtils.startOfWeek(dateIndex); if (timeSeries.getDataItem(new Week(dateIndex)) == null) { timeSeries.add(new Week(dateIndex), 0.0d); } dateIndex = DateUtils.addDays(dateIndex, 7); } else if (Month.class.equals(period)) { dateIndex = DateUtils.startOfMonth(dateIndex); if (timeSeries.getDataItem(new Month(dateIndex)) == null) { timeSeries.add(new Month(dateIndex), 0.0d); } dateIndex = DateUtils.addMonths(dateIndex, 1); } else if (Year.class.equals(period)) { dateIndex = DateUtils.startOfYear(dateIndex); if (timeSeries.getDataItem(new Year(dateIndex)) == null) { timeSeries.add(new Year(dateIndex), 0.0d); } dateIndex = DateUtils.addYears(dateIndex, 1); } else { // un-expected time period throw new Exception("The supplied time period " + period.getName() + " is unsupported, use Second, Minute, Hour, Day, Week, Month, and Year."); } } }} Link to comment Share on other sites More sharing options...
mixcom Posted March 24, 2010 Share Posted March 24, 2010 Hello rreganjr,I'm really interested in your customizer class but I get errors compiling it on my system (see messages below). I can't find the DateUtils class anywhere. Can you tell me to find it ? If it's custom made can you send it to me ? Thanks, MixcomCode:JRTimeSeriesCustomizerEmptyDateFiller.java:62: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.startOfDay(dateIndex); ^JRTimeSeriesCustomizerEmptyDateFiller.java:66: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.addDays(dateIndex, 1); ^JRTimeSeriesCustomizerEmptyDateFiller.java:68: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.startOfHour(dateIndex); ^JRTimeSeriesCustomizerEmptyDateFiller.java:72: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.addHours(dateIndex, 1); ^JRTimeSeriesCustomizerEmptyDateFiller.java:74: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.startOfMinute(dateIndex); ^JRTimeSeriesCustomizerEmptyDateFiller.java:78: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.addMinutes(dateIndex, 1); ^JRTimeSeriesCustomizerEmptyDateFiller.java:80: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.startOfSecond(dateIndex); ^JRTimeSeriesCustomizerEmptyDateFiller.java:84: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.addSeconds(dateIndex, 1); ^JRTimeSeriesCustomizerEmptyDateFiller.java:86: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.startOfWeek(dateIndex); ^JRTimeSeriesCustomizerEmptyDateFiller.java:90: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.addDays(dateIndex, 7); ^JRTimeSeriesCustomizerEmptyDateFiller.java:92: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.startOfMonth(dateIndex); ^JRTimeSeriesCustomizerEmptyDateFiller.java:96: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.addMonths(dateIndex, 1); ^JRTimeSeriesCustomizerEmptyDateFiller.java:98: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.startOfYear(dateIndex); ^JRTimeSeriesCustomizerEmptyDateFiller.java:102: cannot find symbolsymbol : variable DateUtilslocation: class utils.JRTimeSeriesCustomizerEmptyDateFiller dateIndex = DateUtils.addYears(dateIndex, 1); Link to comment Share on other sites More sharing options...
lithiumfox Posted March 24, 2010 Share Posted March 24, 2010 Hi Mixcom,I also working on a similiar issue, however it seems that many functions in java.util.Date have been deprecated. I have found a similar DateUtils functionality in org.apache.commons.lang.time.DateUtils, howver it is still missing several functions.I am still working on a solution however, not sure as of yet. Thanks Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now