XChart icon indicating copy to clipboard operation
XChart copied to clipboard

Annotation for Date axis

Open mkpaz opened this issue 2 years ago • 2 comments

XYChart.addSeries() accepts a list of java.util.Date, but Annotation* constructor only accepts a double. I tried to convert Date to millis, but annotation is always rendered before the actual date. There's nothing similar in tests or examples, so could someone please tell me what is the proper way to calc annotation position for the Date axis type?

mkpaz avatar Dec 18 '22 15:12 mkpaz

Ok, I think it's a bug. Chart labels should start from 2012, not from 2011.

List<LocalDate> x = new ArrayList<>();
List<Integer> y = new ArrayList<>();

x.add(LocalDate.of(2011, 12, 1));
y.add(10);

for (int year = 2012; year <= 2022; year++) {
    var e = generate(year);
    x.addAll(e.getKey());
    y.addAll(e.getValue());
}

for (int i = 0; i < x.size(); i++) {
    System.out.println(x.get(i) + " - " + y.get(i));
}

Collections.sort(x);

XYChart chart = new XYChartBuilder()
        .width(1600)
        .theme(Styler.ChartTheme.GGPlot2)
        .xAxisTitle("Date")
        .yAxisTitle("Message Count")
        .build();

XYSeries series = chart.addSeries(
        "s1",
        x.stream().map(ld -> Date.from(ld.atStartOfDay(ZoneId.systemDefault()).toInstant())).collect(Collectors.toList()),
        y
);

var aDate = LocalDate.of(2014, 6, 1).atStartOfDay().toInstant(ZoneOffset.UTC);
chart.addAnnotation(new AnnotationLine(aDate.toEpochMilli(), true, false));

static Map.Entry<List<LocalDate>, List<Integer>> generate(int year) {
    var dates = new ArrayList<LocalDate>();
    var values = new ArrayList<Integer>();
    for (int month = 12; month >= 1; month--) {
        dates.add(LocalDate.of(year, month, 10));
        values.add(ThreadLocalRandom.current().nextInt(10, 50));
    }
    return Map.entry(dates, values);
}

image

mkpaz avatar Dec 18 '22 17:12 mkpaz

Yup, definitely a bug. For this specific time scale it seems.

timmolter avatar Dec 25 '22 17:12 timmolter