Skip to content

WeekOfMonth vs LastWeekOfMonth inconsistency #18672

Closed
@jbrockmendel

Description

@jbrockmendel

https://github.com/pandas-dev/pandas/blob/master/pandas/tseries/offsets.py#L1496

WeekOfMonth and LastWeekOfMonth have small differences in how they construct getOffsetOfMonth and then in what they do with it. It looks fishy. Any idea why these are done differently? If there's not a reason for it, I'd like to align+merge them.

class WeekOfMonth(DateOffset):
    [...]
    @apply_wraps
    def apply(self, other):
        base = other
        offsetOfMonth = self.getOffsetOfMonth(other)

        months = self.n
        if months > 0 and offsetOfMonth > other:
            months -= 1
        elif months <= 0 and offsetOfMonth < other:
            months += 1

        other = self.getOffsetOfMonth(shift_month(other, months, 'start'))
        other = datetime(other.year, other.month, other.day, base.hour,
                         base.minute, base.second, base.microsecond)
        return other

    def getOffsetOfMonth(self, dt):
        w = Week(weekday=self.weekday)
        d = datetime(dt.year, dt.month, 1, tzinfo=dt.tzinfo)
        # TODO: Is this DST-safe?
        d = w.rollforward(d)
        return d + timedelta(weeks=self.week)


    def onOffset(self, dt):
        if self.normalize and not _is_normalized(dt):
            return False
        d = datetime(dt.year, dt.month, dt.day, tzinfo=dt.tzinfo)
        return d == self.getOffsetOfMonth(dt)

class LastWeekOfMonth(DateOffset):
    [...]
    @apply_wraps
    def apply(self, other):
        offsetOfMonth = self.getOffsetOfMonth(other)

        months = self.n
        if months > 0 and offsetOfMonth > other:
            months -= 1
        elif months <= 0 and offsetOfMonth < other:
            months += 1

        return self.getOffsetOfMonth(shift_month(other, months, 'start'))

    def getOffsetOfMonth(self, dt):
        m = MonthEnd()
        d = datetime(dt.year, dt.month, 1, dt.hour, dt.minute,
                     dt.second, dt.microsecond, tzinfo=dt.tzinfo)
        eom = m.rollforward(d)
        # TODO: Is this DST-safe?
        w = Week(weekday=self.weekday)
        return w.rollback(eom)

    def onOffset(self, dt):
        if self.normalize and not _is_normalized(dt):
            return False
        return dt == self.getOffsetOfMonth(dt)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions