Geoffrey De Smet
Geoffrey De Smet

Reputation: 27312

JFreeChart: create a chart with java.time.LocalDate or java.time.LocalDateTime

java.util.Date is very error prone. It is dead. Long live java.time.*.

Given a Map<LocalDate, Integer> dateToCountMap, how do I create a JFreeChart chart that shows the count per date?

Upvotes: 3

Views: 766

Answers (1)

trashgod
trashgod

Reputation: 205785

In the case of LocalDate, you can create a time series chart by constructing the corresponding Day, as shown below.

LocalDate ld = entry.getKey();
Day d = new Day(ld.getDayOfMonth(), ld.getMonthValue(), ld.getYear());
series.add(d, entry.getValue());

If you have relevant time zone data, you can use it when constructing the Day. A similar approach can be used for LocalDateTime and any desired concrete RegularTimePeriod. See also the approach shown here and here, given an Instant. Moreover, a custom implementation of XYDataset, seen here, can simply convert the result of toEpochMilli() and return it from getX().

image


import java.awt.Dimension;
import java.awt.EventQueue;
import java.text.DateFormat;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;

/**
 * @see https://stackoverflow.com/a/66713994/230513
 * @see https://stackoverflow.com/a/12481509/230513
 */
public class XYTest {

    private static final int N = 16;

    private XYDataset createDataset() {
        long t = LocalDate.now().toEpochDay();
        Map<LocalDate, Integer> dateToCountMap = new HashMap<>();
        for (int i = 0; i < N; i++) {
            dateToCountMap.put(LocalDate.ofEpochDay(t + i), (int) Math.pow(i, 1.61));
        }
        TimeSeries series = new TimeSeries("Data)");
        for (Map.Entry<LocalDate, Integer> entry : dateToCountMap.entrySet()) {
            LocalDate ld = entry.getKey();
            Day d = new Day(ld.getDayOfMonth(), ld.getMonthValue(), ld.getYear());
            series.add(d, entry.getValue());
        }
        return new TimeSeriesCollection(series);
    }

    private JFreeChart createChart(final XYDataset dataset) {
        JFreeChart chart = ChartFactory.createTimeSeriesChart(
            "Test", "Day", "Value", dataset, false, false, false);
        XYPlot plot = (XYPlot) chart.getPlot();
        DateAxis domain = (DateAxis) plot.getDomainAxis();
        domain.setDateFormatOverride(DateFormat.getDateInstance());
        return chart;
    }

    static void create() {
        JFrame frame = new JFrame("Bar Chart");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        XYTest xyTest = new XYTest();
        XYDataset dataset = xyTest.createDataset();
        JFreeChart chart = xyTest.createChart(dataset);
        ChartPanel chartPanel = new ChartPanel(chart) {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(800, 300);
            }
        };
        frame.add(chartPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(XYTest::create);
    }
}

Upvotes: 4

Related Questions