Skip to content

Eventual bug: The Samoa-esque problem. #252

@kazie

Description

@kazie

Hello there.

I was trying to learn and also validate a bit of whenever, but whilst doing it I think I came across a bug.

The bug is although not a very common case, and you have probably heard about it historically - the Samoa case where they skipped over an entire day.

def test_behaviour_on_samoa_24h_skip():
    # Thursday the 29'th
    _DEC_29_SAMOA = ZonedDateTime(2011, 12, 29, 12, tz="Pacific/Apia")
    # Saturday the 31'st
    _DEC_31_SAMOA = ZonedDateTime(2011, 12, 31, 12, tz="Pacific/Apia")
    ## Week before change dates
    # Thursday the 22'nd
    _DEC_22_SAMOA = ZonedDateTime(2011, 12, 22, 12, tz="Pacific/Apia")
    # Friday the 23'rd
    _DEC_23_SAMOA = ZonedDateTime(2011, 12, 23, 12, tz="Pacific/Apia")
    # Saturday the 24'th
    _DEC_24_SAMOA = ZonedDateTime(2011, 12, 24, 12, tz="Pacific/Apia")

    assert _DEC_29_SAMOA.replace_time(Time(hour=23)) + hours(
        1
    ) == _DEC_31_SAMOA.replace_time(Time(hour=0))
    assert (_DEC_31_SAMOA - _DEC_29_SAMOA) == hours(24)

    # Same weekday, week before skip
    assert _DEC_22_SAMOA + weeks(1) == _DEC_29_SAMOA
    # FIXME: Bugs, 22 + 8 days should be 31
    # assert _DEC_22_SAMOA + days(8) == _DEC_31_SAMOA

    # Friday week before, before timezone jumped over the day
    # TODO: Remove me, 23 + week should be the removed day, and thus move forward?
    assert _DEC_23_SAMOA + weeks(1) == _DEC_29_SAMOA
    # FIXME: Commented since bugs!
    # assert _DEC_23_SAMOA + days(7) == _DEC_31_SAMOA
    # Saturday week before skip
    assert _DEC_24_SAMOA + weeks(1) == _DEC_31_SAMOA
    assert _DEC_24_SAMOA + days(5) == _DEC_29_SAMOA
    # FIXME: Commented since bugs!
    # assert _DEC_24_SAMOA + days(6) == _DEC_31_SAMOA
    # Thursday plus one week == Friday plus one week.
    # FIXME: Shouldn't these not work? As 23 + 7 days or Week is 31?
    assert _DEC_22_SAMOA + weeks(1) == _DEC_23_SAMOA + weeks(1)
    assert _DEC_22_SAMOA + days(7) == _DEC_23_SAMOA + days(7)

To have something to visualise the local calendar, I have attached a picture:

Image

Here we have the two cases of, it being Friday the 23'rd.

So, if you're on the 24'th on the calendar, and jump six days, that should bring you to the 31'st, but the test fails as:

ZonedDateTime(2011-12-29 12:00:00-10:00[Pacific/Apia]) != ZonedDateTime(2011-12-31 12:00:00+14:00[Pacific/Apia])

Expected :ZonedDateTime(2011-12-31 12:00:00+14:00[Pacific/Apia])
Actual   :ZonedDateTime(2011-12-29 12:00:00-10:00[Pacific/Apia])

>       assert _DEC_24_SAMOA + days(6) == _DEC_31_SAMOA
E       assert (ZonedDateTime(2011-12-24 12:00:00-10:00[Pacific/Apia]) + DateDelta(P6d)) == ZonedDateTime(2011-12-31 12:00:00+14:00[Pacific/Apia])
E        +  where DateDelta(P6d) = days(6)

Looking at the calendar, it surely should have been the 31st, if you go 6 days forward.


Same with 23'rd and 7 days.

ZonedDateTime(2011-12-29 12:00:00-10:00[Pacific/Apia]) != ZonedDateTime(2011-12-31 12:00:00+14:00[Pacific/Apia])

Expected :ZonedDateTime(2011-12-31 12:00:00+14:00[Pacific/Apia])
Actual   :ZonedDateTime(2011-12-29 12:00:00-10:00[Pacific/Apia])

>       assert _DEC_23_SAMOA + days(7) == _DEC_31_SAMOA
E       assert (ZonedDateTime(2011-12-23 12:00:00-10:00[Pacific/Apia]) + DateDelta(P7d)) == ZonedDateTime(2011-12-31 12:00:00+14:00[Pacific/Apia])
E        +  where DateDelta(P7d) = days(7)

I am not sure if 23 + Week can as easily be defined, but I would expect week logic to be "same weekday or next" which seems to be the implementation in Java(Kotlin) when I wrote a similar test to check behaviour.

package org.example

import java.time.Duration
import java.time.ZoneId
import java.time.ZonedDateTime
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals

class Samoa {

    @Test
    fun testFunnySamoa() {
        val samoaZone: ZoneId = ZoneId.of("Pacific/Apia")

        val DEC_29_SAMOA: ZonedDateTime = ZonedDateTime.of(2011, 12, 29, 12, 0, 0, 0, samoaZone)
        val DEC_31_SAMOA: ZonedDateTime = ZonedDateTime.of(2011, 12, 31, 12, 0, 0, 0, samoaZone)
        val DEC_22_SAMOA: ZonedDateTime = ZonedDateTime.of(2011, 12, 22, 12, 0, 0, 0, samoaZone)
        val DEC_23_SAMOA: ZonedDateTime = ZonedDateTime.of(2011, 12, 23, 12, 0, 0, 0, samoaZone)
        val DEC_24_SAMOA: ZonedDateTime = ZonedDateTime.of(2011, 12, 24, 12, 0, 0, 0, samoaZone)

        // Test hour addition crossing the date line
        assertEquals(
            DEC_31_SAMOA.withHour(0),
            DEC_29_SAMOA.withHour(23).plusHours(1)
        )


        // Test duration between dates
        assertEquals(24, Duration.between(DEC_29_SAMOA, DEC_31_SAMOA).toHours())


        // Test week additions
        assertEquals(DEC_29_SAMOA, DEC_22_SAMOA.plusWeeks(1))
        assertEquals(DEC_31_SAMOA, DEC_23_SAMOA.plusWeeks(1))
        assertEquals(DEC_31_SAMOA, DEC_23_SAMOA.plusDays(7))
        assertEquals(DEC_31_SAMOA, DEC_24_SAMOA.plusWeeks(1))


        // Test day additions
        assertEquals(DEC_29_SAMOA, DEC_24_SAMOA.plusDays(5))
        assertEquals(DEC_31_SAMOA, DEC_24_SAMOA.plusDays(6))

        // Test week consistency
        assertNotEquals(DEC_22_SAMOA.plusWeeks(1), DEC_23_SAMOA.plusWeeks(1))
        assertNotEquals(DEC_22_SAMOA.plusDays(7), DEC_23_SAMOA.plusDays(7))

        // Test what buggs in whatever
        assertEquals(DEC_31_SAMOA,DEC_23_SAMOA.plusWeeks(1))
        assertEquals(DEC_31_SAMOA,DEC_24_SAMOA.plusWeeks(1))
        assertEquals(DEC_31_SAMOA,DEC_24_SAMOA.plusDays(6))
        assertEquals(DEC_31_SAMOA,DEC_22_SAMOA.plusDays(8))
    }

}

I would want to say that I am missing something trivial, but in this case looking at the calendar and "walking days" I can only strongly believe that there is some small bug hiding under the rocks around here 🐛

Metadata

Metadata

Assignees

No one assigned

    Labels

    Long termLow priority for now

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions