4

I'm using the Java 8 time library to determine the previous weeks and year from today's date and then store those values in a map. I think I've figured out how to properly get the weeks, but I'm not entirely sure what the correct way is to get the year. Current code below:

int weeksLimit = 5; // this value is passed into the method, but just setting it here as an example
Map<Integer, Integer> yearWeeks = new HashMap<Integer, Integer>();
LocalDate ld = LocalDate.now();
WeekFields weekFields = WeekFields.of(DayOfWeek.SUNDAY, 4);
for (int i = weeksLimit; i > 0; i--) {
    LocalDate pastDate = ld.minusWeeks(i);
    yearWeeks.put(pastDate.getYear(), pastDate.get(weekFields.weekOfWeekBasedYear()));
}

I don't believe pastDate.getYear() is the correct usage. As the result I want is something along the lines of:

  • 1/12/2020 - 1/18/2020 = Week 3, Year 2020
  • 1/05/2020 - 1/11/2020 = Week 2, Year 2020
  • 12/29/2019 - 1/04/2020 = Week 1, Year 2020
  • 12/22/2019 - 12/28/2019 = Week 52, Year 2019

Could someone please help me figure out how to correctly get the year I want?

Pr0pagate
  • 199
  • 2
  • 12
  • 4
    (1) You probably want week based year rather than year. (2) You can’t put those values in a map with year as key and week as value. In your example year 2020 comes three times, but a given key can appear only once in a map. – Ole V.V. Jan 22 '20 at 19:04
  • 5
    I think that Malta is probably the only country in the world using `WeekFields.of(DayOfWeek.SUNDAY, 4)`. If you want this because it’s Maltese, `WeekFields.of(Locale.forLanguageTag("mt_MT"))` may convey that better. – Ole V.V. Jan 22 '20 at 19:22
  • 1
    Are the first and the last day of each week required parts of the result,or do you only need the years and week numbers? – Ole V.V. Jan 22 '20 at 20:16

1 Answers1

5

I can’t tell which is the right data structure for your purpose. A map with year as key and week as value won’t do for holding your example data. In your example year 2020 comes three times, but a given key can appear only once in a map. In the following example I am assuming a map that maps each week based year to a list of week numbers for that year.

    WeekFields weekFields = WeekFields.of(Locale.forLanguageTag("mt_MT"));

    int weeksLimit = 5; // this value is passed into the method, but just setting it here as an example

    LocalDate today = LocalDate.now(ZoneId.of("Europe/Malta"));
    Map<Integer, List<Integer>> yearWeeks = IntStream.rangeClosed(1, weeksLimit)
            .mapToObj(i -> today.minusWeeks(i))
            .collect(Collectors.groupingBy(ld -> ld.get(weekFields.weekBasedYear()),
                    Collectors.mapping(ld -> ld.get(weekFields.weekOfWeekBasedYear()),
                            Collectors.toList())));

    System.out.println(yearWeeks);

When I ran the snippet just now, the output was:

{2019=[52, 51], 2020=[3, 2, 1]}

I don’t expect to be there yet, but I am not putting more effort into this until I understand your requirements more clearly.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Thank you! Yes, this is the correct solution for what I am looking for. You are correct in terms of using the weekBasedYear() method, as well as a single map not suiting my needs. I personally ended up using the apache.commons.collections4.MultiValuedMap just to slightly reduce the lines of code needed, but ultimately it was the same solution you've described here. – Pr0pagate Jan 22 '20 at 21:03
  • 2
    Thanks for reporting back! Glad it was helpful. Yes, the `MultiValiedMap` sounds right. – Ole V.V. Jan 23 '20 at 05:18