arrow icon indicating copy to clipboard operation
arrow copied to clipboard

Add halfhour frame to ceil and floor

Open glennpierce opened this issue 6 years ago • 2 comments

Would it be possible to add a halfhour to _get_frames to allow ceil and round to round to the nearest half hour ?

Or is that currently possible ?

glennpierce avatar Apr 18 '18 10:04 glennpierce

it's not currently possible.

But you might do some custom logic to compare a range of minutes, do a replace and then a ceiling/floor with a minute frame, perhaps as a quick hack.

krisfremen avatar Apr 20 '18 11:04 krisfremen

Not tested too much but in the end I did this hack

def span(self, frame, count=1):
        ''' Returns two new :class:`Arrow <arrow.arrow.Arrow>` objects, representing the timespan
        of the :class:`Arrow <arrow.arrow.Arrow>` object in a given timeframe.
        :param frame: the timeframe.  Can be any ``datetime`` property (day, hour, minute...).
        :param count: (optional) the number of frames to span.
        Supported frame values: year, quarter, month, week, day, hour, minute, second.
        Usage::
            >>> arrow.utcnow()
            <Arrow [2013-05-09T03:32:36.186203+00:00]>
            >>> arrow.utcnow().span('hour')
            (<Arrow [2013-05-09T03:00:00+00:00]>, <Arrow [2013-05-09T03:59:59.999999+00:00]>)
            >>> arrow.utcnow().span('day')
            (<Arrow [2013-05-09T00:00:00+00:00]>, <Arrow [2013-05-09T23:59:59.999999+00:00]>)
            >>> arrow.utcnow().span('day', count=2)
            (<Arrow [2013-05-09T00:00:00+00:00]>, <Arrow [2013-05-10T23:59:59.999999+00:00]>)
        '''

        frame_absolute, frame_relative, relative_steps = (None, None, None)

        if frame == 'halfhour':
            frame_absolute, frame_relative, relative_steps = ("halfhour", 'minutes', 30) 
        else:
            frame_absolute, frame_relative, relative_steps = self._get_frames(frame)

        if frame_absolute == 'halfhour':
            attr = 'minute'
        elif frame_absolute == 'week':
            attr = 'day'
        elif frame_absolute == 'quarter':
            attr = 'month'
        else:
            attr = frame_absolute

        index = self._ATTRS.index(attr)
        frames = self._ATTRS[:index + 1]

        values = [getattr(self, f) for f in frames]

        for i in range(3 - len(values)):
            values.append(1)

        floor = self.__class__(*values, tzinfo=self.tzinfo)

        if frame_absolute == 'halfhour':
            floor = floor + relativedelta(minutes=-(self.minute % 30))
        elif frame_absolute == 'week':
            floor = floor + relativedelta(days=-(self.isoweekday() - 1)) 
        elif frame_absolute == 'quarter':
            floor = floor + relativedelta(months=-((self.month - 1) % 3)) 

        ceil = floor + relativedelta(
            **{frame_relative: count * relative_steps}) + relativedelta(microseconds=-1)

        return floor, ceil


arrow.Arrow.span = span

glennpierce avatar Apr 20 '18 11:04 glennpierce