3

For what I can only assume is a timezone issue, the following code yields different week of year values for the same day, but different times:

Note, the code is written in Kotlin

Example

fun main(args: Array<String>) {
    
    val middaySundayAfterEpoch = Instant.EPOCH + Duration
        .ZERO
        .plusDays(3)
        .plusHours(12)

    val almostMidnightSundayAfterEpoch = Instant.EPOCH + Duration
        .ZERO
        .plusDays(3)
        .plusHours(23)

    println(getWeekOfYear(middaySundayAfterEpoch))
    println(getWeekOfYear(almostMidnightSundayAfterEpoch))
}

fun getWeekOfYear(instant: Instant): Int {
    val calendar: Calendar = Calendar.getInstance()
    calendar.time = Date.from(instant)

    return calendar.get(Calendar.WEEK_OF_YEAR)
}

Results

1

2

Assumptions

  • Sunday, 12:00 is actually Sunday, 13:00 in the calendar
  • Sunday, 23:00 is actually Monday, 00:00 in the calendar

Question

How do I modify this to ignore the time zone, so that both times occur in the same week?

Community
  • 1
  • 1
Matthew Layton
  • 39,871
  • 52
  • 185
  • 313
  • 2
    Never mix the terrible old date-time classes (`Calendar` & `Date`) with the modern *java.time* classes (`Instant`). As of the adoption of JSR 310 in Java 8 and later, the legacy classes are supplanted entirely. Convert to/from the legacy classes only when interoperating with old code not yet updated to *java.time*. In other words, avoid `Calendar` & `Date` whenever possible. – Basil Bourque Jan 03 '19 at 22:48

1 Answers1

5

You should never use the legacy java.util.Date and java.util.Calendar if you can possibly avoid them, this being one of many reasons.

The ZonedDateTime object provides a way to get this:

instant.atZone(ZoneId.of("UTC")).get(IsoFields.WEEK_OF_WEEK_BASED_YEAR)

EDIT: A previous version of this answer used the system default time, as well as ChronoUnit.ALIGNED_WEEK_OF_YEAR. This considers 1-7 January to be "week 1" of the year, regardless of on which day of the week 1 January lies in a particular year. However, it will be based on the date part of the ZonedDateTime.

Joe C
  • 15,324
  • 8
  • 38
  • 50