Search code examples
pythonpandasdatetimeunix-timestamputc

Python and Pandas: How to round Up/Down unix timestamp (utc) on different resolutions: 1min-5min-15min-30min-1H-1D?


Given the following time resolutions examples, what would be the fastest way to round UNIX time to get the results shown below? Both in simple python and in pandas dataframes?

import time
unix_current = int(time.time())
unix_from_down_example = int("1453823631")
unix_from_up_example = int("1453820476")

Round Down/Up to 1 Minute

+---------------+---------------------+------------+
|               |                     | Unix (UTC) |
| from          | 26.01.2016 15:53:51 | 1453823631 |
| to round down | 26.01.2016 15:53:00 | 1453823580 |
|               |                     |            |
| from          | 26.01.2016 15:01:16 | 1453820476 |
| to round up   | 26.01.2016 15:02:00 | 1453820520 |
+---------------+---------------------+------------+

Round Down/Up to 5 Minutes

+---------------+---------------------+------------+
|               |                     | Unix (UTC) |
| from          | 26.01.2016 15:53:51 | 1453823631 |
| to round down | 26.01.2016 15:50:00 | 1453823400 |
|               |                     |            |
| from          | 26.01.2016 15:01:16 | 1453820476 |
| to round up   | 26.01.2016 15:05:00 | 1453820700 |
+---------------+---------------------+------------+

Round Down/Up to 15 Minutes

+---------------+---------------------+------------+
|               |                     | Unix (UTC) |
| from          | 26.01.2016 15:53:51 | 1453823631 |
| to round down | 26.01.2016 15:45:00 | 1453823100 |
|               |                     |            |
| from          | 26.01.2016 15:01:16 | 1453820476 |
| to round up   | 26.01.2016 15:15:00 | 1453821300 |
+---------------+---------------------+------------+

Round Down/Up to 30 Minutes

+---------------+---------------------+------------+
|               |                     | Unix (UTC) |
| from          | 26.01.2016 15:53:51 | 1453823631 |
| to round down | 26.01.2016 15:30:00 | 1453822200 |
|               |                     |            |
| from          | 26.01.2016 15:01:16 | 1453820476 |
| to round up   | 26.01.2016 15:30:00 | 1453822200 |
+---------------+---------------------+------------+

Round Down/Up to 1 Hour

+---------------+---------------------+------------+
|               |                     | Unix (UTC) |
| from          | 26.01.2016 15:53:51 | 1453823631 |
| to round down | 26.01.2016 15:00:00 | 1453820400 |
|               |                     |            |
| from          | 26.01.2016 15:01:16 | 1453820476 |
| to round up   | 26.01.2016 16:00:00 | 1453824000 |
+---------------+---------------------+------------+

Round Down/Up to 1 Day

+---------------+---------------------+------------+
|               |                     | Unix (UTC) |
| from          | 26.01.2016 15:53:51 | 1453823631 |
| to round down | 26.01.2016 00:00:00 | 1453766400 |
|               |                     |            |
| from          | 26.01.2016 15:01:16 | 1453820476 |
| to round up   | 27.01.2016 00:00:00 | 1453852800 |
+---------------+---------------------+------------+

I used this website as a conversion reference for the examples given.


Solution

  • A generic formula for rounding DOWN:

    n // <Number of seconds> * <Number of seconds>
    

    A generic formula for rounding UP:

    n // <Number of seconds> * <Number of seconds> + <Number of seconds>
    

    Function:

    def round_unix_date(dt_series, seconds=60, up=False):
        return dt_series // seconds * seconds + seconds * up
    

    Usage:

    In [204]: df
    Out[204]:
            Date1       Date2
    0  1453823631  1453820476
    1  1453823631  1453820476
    2  1453823631  1453820476
    
    In [205]: round_unix_date(df.Date1, 5*60)
    Out[205]:
    0    1453823400
    1    1453823400
    2    1453823400
    Name: Date1, dtype: int64
    
    In [206]: round_unix_date(df.Date2, 5*60, up=True)
    Out[206]:
    0    1453820700
    1    1453820700
    2    1453820700
    Name: Date2, dtype: int64
    

    Demo (rounding DOWN):

    In [165]: n // (1 * 60) * (1 * 60)
    Out[165]: 1453823580
    
    In [166]: n // (5 * 60) * (5 * 60)
    Out[166]: 1453823400
    
    In [167]: n = 1453823631
    
    In [168]: n // (1 * 60) * (1 * 60)
    Out[168]: 1453823580
    
    In [169]: n // (5 * 60) * (5 * 60)
    Out[169]: 1453823400
    
    In [170]: n // (15 * 60) * (15 * 60)
    Out[170]: 1453823100
    
    In [171]: n // (30 * 60) * (30 * 60)
    Out[171]: 1453822200
    
    In [172]: n // (60 * 60) * (60 * 60)
    Out[172]: 1453820400
    
    In [173]: n // (24 * 60 * 60) * (24 * 60 * 60)
    Out[173]: 1453766400
    

    Demo (rounding UP):

    In [188]: n = 1453820476
    
    In [189]: n // (1 * 60) * (1 * 60) + 60
    Out[189]: 1453820520
    
    In [191]: n // (5 * 60) * (5 * 60) + 5*60
    Out[191]: 1453820700
    
    In [192]: n // (15 * 60) * (15 * 60) + 15*60
    Out[192]: 1453821300
    
    ...
    

    UPDATE:

    In [226]: round_unix_date(df.Date1, 24*60*60)
    Out[226]:
    0    1453766400
    1    1453766400
    2    1453766400
    Name: Date1, dtype: int64
    
    In [227]: round_unix_date(df.Date2, 24*60*60, up=True)
    Out[227]:
    0    1453852800
    1    1453852800
    2    1453852800
    Name: Date2, dtype: int64