Skip to content

WeekOfMonth vs LastWeekOfMonth inconsistency #18672

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jbrockmendel opened this issue Dec 6, 2017 · 2 comments · Fixed by #18875
Closed

WeekOfMonth vs LastWeekOfMonth inconsistency #18672

jbrockmendel opened this issue Dec 6, 2017 · 2 comments · Fixed by #18875
Labels
Bug Frequency DateOffsets
Milestone

Comments

@jbrockmendel
Copy link
Member

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)

@jbrockmendel
Copy link
Member Author

jbrockmendel commented Dec 6, 2017

TL;DR look at WeekOfMonth.getOffsetOfMonth. Why would we drop hour minute second but keep tzinfo?

@jbrockmendel
Copy link
Member Author

@gfyoung There are a whole bunch of (offset+timezone)-related issues that I need input on before I can fix (many of them found when running tests with hypothesis). Is there someone I can ask about these other than jreback? I bug him enough as it is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Frequency DateOffsets
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants