Python datetimes made easy

Overview

Pendulum

Pendulum Build status

Python datetimes made easy.

Supports Python 2.7 and 3.4+.

>>> import pendulum

>>> now_in_paris = pendulum.now('Europe/Paris')
>>> now_in_paris
'2016-07-04T00:49:58.502116+02:00'

# Seamless timezone switching
>>> now_in_paris.in_timezone('UTC')
'2016-07-03T22:49:58.502116+00:00'

>>> tomorrow = pendulum.now().add(days=1)
>>> last_week = pendulum.now().subtract(weeks=1)

>>> past = pendulum.now().subtract(minutes=2)
>>> past.diff_for_humans()
>>> '2 minutes ago'

>>> delta = past - last_week
>>> delta.hours
23
>>> delta.in_words(locale='en')
'6 days 23 hours 58 minutes'

# Proper handling of datetime normalization
>>> pendulum.datetime(2013, 3, 31, 2, 30, tz='Europe/Paris')
'2013-03-31T03:30:00+02:00' # 2:30 does not exist (Skipped time)

# Proper handling of dst transitions
>>> just_before = pendulum.datetime(2013, 3, 31, 1, 59, 59, 999999, tz='Europe/Paris')
'2013-03-31T01:59:59.999999+01:00'
>>> just_before.add(microseconds=1)
'2013-03-31T03:00:00+02:00'

Why Pendulum?

Native datetime instances are enough for basic cases but when you face more complex use-cases they often show limitations and are not so intuitive to work with. Pendulum provides a cleaner and more easy to use API while still relying on the standard library. So it's still datetime but better.

Unlike other datetime libraries for Python, Pendulum is a drop-in replacement for the standard datetime class (it inherits from it), so, basically, you can replace all your datetime instances by DateTime instances in you code (exceptions exist for libraries that check the type of the objects by using the type function like sqlite3 or PyMySQL for instance).

It also removes the notion of naive datetimes: each Pendulum instance is timezone-aware and by default in UTC for ease of use.

Pendulum also improves the standard timedelta class by providing more intuitive methods and properties.

Why not Arrow?

Arrow is the most popular datetime library for Python right now, however its behavior and API can be erratic and unpredictable. The get() method can receive pretty much anything and it will try its best to return something while silently failing to handle some cases:

arrow.get('2016-1-17')
# <Arrow [2016-01-01T00:00:00+00:00]>

pendulum.parse('2016-1-17')
# <Pendulum [2016-01-17T00:00:00+00:00]>

arrow.get('20160413')
# <Arrow [1970-08-22T08:06:53+00:00]>

pendulum.parse('20160413')
# <Pendulum [2016-04-13T00:00:00+00:00]>

arrow.get('2016-W07-5')
# <Arrow [2016-01-01T00:00:00+00:00]>

pendulum.parse('2016-W07-5')
# <Pendulum [2016-02-19T00:00:00+00:00]>

# Working with DST
just_before = arrow.Arrow(2013, 3, 31, 1, 59, 59, 999999, 'Europe/Paris')
just_after = just_before.replace(microseconds=1)
'2013-03-31T02:00:00+02:00'
# Should be 2013-03-31T03:00:00+02:00

(just_after.to('utc') - just_before.to('utc')).total_seconds()
-3599.999999
# Should be 1e-06

just_before = pendulum.datetime(2013, 3, 31, 1, 59, 59, 999999, 'Europe/Paris')
just_after = just_before.add(microseconds=1)
'2013-03-31T03:00:00+02:00'

(just_after.in_timezone('utc') - just_before.in_timezone('utc')).total_seconds()
1e-06

Those are a few examples showing that Arrow cannot always be trusted to have a consistent behavior with the data you are passing to it.

Limitations

Even though the DateTime class is a subclass of datetime there are some rare cases where it can't replace the native class directly. Here is a list (non-exhaustive) of the reported cases with a possible solution, if any:

  • sqlite3 will use the type() function to determine the type of the object by default. To work around it you can register a new adapter:
from pendulum import DateTime
from sqlite3 import register_adapter

register_adapter(DateTime, lambda val: val.isoformat(' '))
  • mysqlclient (former MySQLdb) and PyMySQL will use the type() function to determine the type of the object by default. To work around it you can register a new adapter:
import MySQLdb.converters
import pymysql.converters

from pendulum import DateTime

MySQLdb.converters.conversions[DateTime] = MySQLdb.converters.DateTime2literal
pymysql.converters.conversions[DateTime] = pymysql.converters.escape_datetime
  • django will use the isoformat() method to store datetimes in the database. However since pendulum is always timezone aware the offset information will always be returned by isoformat() raising an error, at least for MySQL databases. To work around it you can either create your own DateTimeField or use the previous workaround for MySQLdb:
from django.db.models import DateTimeField as BaseDateTimeField
from pendulum import DateTime


class DateTimeField(BaseDateTimeField):

    def value_to_string(self, obj):
        val = self.value_from_object(obj)

        if isinstance(value, DateTime):
            return value.to_datetime_string()

        return '' if val is None else val.isoformat()

Resources

Contributing

Contributions are welcome, especially with localization.

Getting started

To work on the Pendulum codebase, you'll want to clone the project locally and install the required depedendencies via poetry.

$ git clone [email protected]:sdispater/pendulum.git
$ poetry install

Localization

If you want to help with localization, there are two different cases: the locale already exists or not.

If the locale does not exist you will need to create it by using the clock utility:

./clock locale create <your-locale>

It will generate a directory in pendulum/locales named after your locale, with the following structure:

<your-locale>/
    - custom.py
    - locale.py

The locale.py file must not be modified. It contains the translations provided by the CLDR database.

The custom.py file is the one you want to modify. It contains the data needed by Pendulum that are not provided by the CLDR database. You can take the en data as a reference to see which data is needed.

You should also add tests for the created or modified locale.

Comments
  • Could not build wheels for pendulum which use PEP 517

    Could not build wheels for pendulum which use PEP 517

    • [x] I am on the latest Pendulum version.

    • [x] I have searched the issues of this repo and believe that this is not a duplicate.

    • Alpine 3.11 in Docker

    • Pendulum 2.1.0

    Issue

    I get an error about PEP 517 when trying to install Pendulum. The following Dockerfile (run with docker build .) reproduces the issue.

    The error is ERROR: Could not build wheels for pendulum which use PEP 517 and cannot be installed directly

    FROM python:3.7-alpine3.11
    RUN apk update \
        && apk add gcc musl-dev python3-dev py3-setuptools libffi libffi-dev openssl-dev \
        && pip3 install pendulum==2.1.0
    
    opened by weskerfoot 35
  • datetime compatibility - timestamp int vs function

    datetime compatibility - timestamp int vs function

    Does pendulum aim for full api compatibility with datetime.datetime? It looks like pendulum's timestamp is a property, while datetime's timestamp is a function:

    from datetime import datetime, timezone
    import pendulum
    d = datetime.now(timezone.utc)
    p = pendulum.now(timezone.utc)
    
    d.timestamp
    # <function datetime.timestamp>
    
    d.timestamp()
    # 1478671704.494979
    
    p.timestamp
    # 1478671596
    

    I really wanted to use pendulum under the covers and expose the interface as datetime, but this is a property I expect users to depend on having the usual signature.

    enhancement 
    opened by numberoverzero 29
  • ERROR: Failed building wheel for pendulum

    ERROR: Failed building wheel for pendulum

    • [X] I am on the latest Pendulum version.
    • [X] I have searched the issues of this repo and believe that this is not a duplicate.
    • OS version and name: Windows 10
    • Pendulum version: 2.1.0

    Issue

    Python: Python 3.8.2 PIP: pip 20.0.2

    I am encountering an error installing Python Twitch IRC:

    pip install python-twitch-irc

    Full error message:

    Collecting python-twitch-irc
      Using cached python_twitch_irc-1.1.0-py3-none-any.whl (6.2 kB)
    Collecting pendulum
      Using cached pendulum-2.1.0.tar.gz (80 kB)
      Installing build dependencies ... done
      Getting requirements to build wheel ... done
        Preparing wheel metadata ... done
    Collecting pydle
      Using cached pydle-0.9.3-py3-none-any.whl (43 kB)
    Collecting python-dateutil<3.0,>=2.6
      Using cached python_dateutil-2.8.1-py2.py3-none-any.whl (227 kB)
    Collecting pytzdata>=2018.3
      Using cached pytzdata-2019.3-py2.py3-none-any.whl (489 kB)
    Requirement already satisfied: six>=1.5 in c:\users\nigel\appdata\local\packages\pythonsoftwarefoundation.python.3.8_qbz5n2kfra8p0\localcache\local-packages\python38\site-packages (from python-dateutil<3.0,>=2.6->pendulum->python-twitch-irc) (1.14.0)
    Building wheels for collected packages: pendulum
      Building wheel for pendulum (PEP 517) ... error
      ERROR: Command errored out with exit status 1:
       command: 'C:\Users\nigel\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\python.exe' 'C:\Users\nigel\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\pip\_vendor\pep517\_in_process.py' build_wheel 'C:\Users\nigel\AppData\Local\Temp\tmph3lnsr6j'
           cwd: C:\Users\nigel\AppData\Local\Temp\pip-install-vj7m5mv2\pendulum
      Complete output (24 lines):
      Traceback (most recent call last):
        File "setup.py", line 2, in <module>
          from setuptools import setup
      ModuleNotFoundError: No module named 'setuptools'
      Traceback (most recent call last):
        File "C:\Users\nigel\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\pip\_vendor\pep517\_in_process.py", line 257, in <module>
          main()
        File "C:\Users\nigel\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\pip\_vendor\pep517\_in_process.py", line 240, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
        File "C:\Users\nigel\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\pip\_vendor\pep517\_in_process.py", line 181, in build_wheel
          return _build_backend().build_wheel(wheel_directory, config_settings,
        File "C:\Users\nigel\AppData\Local\Temp\pip-build-env-6ft1gs0c\overlay\Lib\site-packages\poetry\core\masonry\api.py", line 57, in build_wheel
          return unicode(WheelBuilder.make_in(poetry, Path(wheel_directory)))
        File "C:\Users\nigel\AppData\Local\Temp\pip-build-env-6ft1gs0c\overlay\Lib\site-packages\poetry\core\masonry\builders\wheel.py", line 56, in make_in
          wb.build()
        File "C:\Users\nigel\AppData\Local\Temp\pip-build-env-6ft1gs0c\overlay\Lib\site-packages\poetry\core\masonry\builders\wheel.py", line 82, in build
          self._build(zip_file)
        File "C:\Users\nigel\AppData\Local\Temp\pip-build-env-6ft1gs0c\overlay\Lib\site-packages\poetry\core\masonry\builders\wheel.py", line 102, in _build
          self._run_build_command(setup)
        File "C:\Users\nigel\AppData\Local\Temp\pip-build-env-6ft1gs0c\overlay\Lib\site-packages\poetry\core\masonry\builders\wheel.py", line 130, in _run_build_command
          subprocess.check_call(
        File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.752.0_x64__qbz5n2kfra8p0\lib\subprocess.py", line 364, in check_call
          raise CalledProcessError(retcode, cmd)
      subprocess.CalledProcessError: Command '['C:\\Users\\nigel\\AppData\\Local\\Microsoft\\WindowsApps\\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\\python.exe', 'setup.py', 'build', '-b', 'build']' returned non-zero exit status 1.
      ----------------------------------------
      ERROR: Failed building wheel for pendulum
    Failed to build pendulum
    ERROR: Could not build wheels for pendulum which use PEP 517 and cannot be installed directly
    

    Projects are up-to-date:

    Command:

    python -m pip install --upgrade pip setuptools wheel

    Output:

    Requirement already up-to-date: pip in c:\users\nigel\appdata\local\packages\pythonsoftwarefoundation.python.3.8_qbz5n2kfra8p0\localcache\local-packages\python38\site-packages (20.0.2)
    Requirement already up-to-date: setuptools in c:\users\nigel\appdata\local\packages\pythonsoftwarefoundation.python.3.8_qbz5n2kfra8p0\localcache\local-packages\python38\site-packages (46.1.3)
    Requirement already up-to-date: wheel in c:\users\nigel\appdata\local\packages\pythonsoftwarefoundation.python.3.8_qbz5n2kfra8p0\localcache\local-packages\python38\site-packages (0.34.2)
    
    opened by SriZbi84 22
  • Parsing issue

    Parsing issue

    Still on that Debian Wheezy (old-stable), I get a strange behaviour:

     % python3
    Python 3.2.3 (default, Feb 20 2013, 17:02:41) 
    [GCC 4.7.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import pendulum
    >>> pendulum.parse('2016-09-04T15:30:09+02:00')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/lib/python3.2/dist-packages/pendulum/pendulum.py", line 242, in parse
        tzinfo=tz
      File "/usr/local/lib/python3.2/dist-packages/pendulum/pendulum.py", line 184, in __init__
        hour, minute, second, microsecond
      File "/usr/local/lib/python3.2/dist-packages/pendulum/tz/timezone.py", line 80, in convert
        return dt.__class__(*converted)
    ValueError: day is out of range for month
    >>> 
     % python
    Python 2.7.3 (default, Jun 20 2016, 16:18:47) 
    [GCC 4.7.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import pendulum
    >>> pendulum.parse('2016-09-04T15:30:09+02:00')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/lib/python2.7/dist-packages/pendulum/pendulum.py", line 242, in parse
        tzinfo=tz
      File "/usr/local/lib/python2.7/dist-packages/pendulum/pendulum.py", line 184, in __init__
        hour, minute, second, microsecond
      File "/usr/local/lib/python2.7/dist-packages/pendulum/tz/timezone.py", line 80, in convert
        return dt.__class__(*converted)
    ValueError: day is out of range for month
    >>> 
    

    This is a quite weird behaviour, on BOTH python versions. Obviously, exact same code works fine on another computer running python3.5 and debian jessie.

    bug 
    opened by guyzmo 19
  • Period length calculation problem

    Period length calculation problem

    I discovered something odd when experimenting with period length calculations around DST change time. Please consider this example:

    tz = pendulum.timezone('America/Los_Angeles')
    start_time = pendulum.parse('2018-03-11 09:00:00+00:00')
    end_time = pendulum.parse('2018-03-11 10:00:00+00:00')
    print((end_time - start_time).hours)     # 1
    print((end_time.in_tz(tz) - start_time).hours)  # 1
    print((end_time - start_time.in_tz(tz)).hours)  # 1
    print((end_time.in_tz(tz) - start_time.in_tz(tz)).hours)  # 2 ?!
    
    p1 = end_time - start_time
    print(start_time + p1 == end_time)   # True
    print(p1.total_hours())  # 1.0
    
    p2 = end_time.in_tz(tz) - start_time.in_tz(tz)
    print(start_time + p2 == end_time)  # False
    print(p2.total_hours())  # 1.0
    
    
    opened by dekoza 17
  • Fix #133: Allow deepcopy on Timezone classes.

    Fix #133: Allow deepcopy on Timezone classes.

    I've added default values to the Timezone classes so that they can be deepcopied. I think it's appropriate to provide these as datetime.tzinfo also has an empty constructor.

    opened by AndreasBackx 15
  • Loader.load portability broken for some pytz installs

    Loader.load portability broken for some pytz installs

    I don't know the full details that make my platform not work with Loader.load but I'm using a Fedora Core 24 box with its stock python3.5 interpretor. I believe that the pytz install I have was installed by pip3 but I'm not 100% sure.

    When I run tests most of them fail because Loader.load is trying to open zoneinfo files in a location that they don't exist. Looking at the code it looks like this is a possibly a non portable way of getting zoneinfo since it makes assumptions about where the zoneinfo files should live.

    I tweaked the exception to print the file location to illustrate..

    ======================================================================
    ERROR: wrap_with_test_now (tests.tz_tests.test_timezone.TimezoneTest)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/home/mayfield/project/pendulum/tests/__init__.py", line 13, in setUp
        LocalTimezone.set_local_timezone(timezone('America/Toronto'))
      File "/home/mayfield/project/pendulum/pendulum/tz/__init__.py", line 16, in timezone
        return Timezone.load(name)
      File "/home/mayfield/project/pendulum/pendulum/tz/timezone.py", line 50, in load
        default_transition_type) = Loader.load(name)
      File "/home/mayfield/project/pendulum/pendulum/tz/loader.py", line 28, in load
        raise TypeError(filepath)
    TypeError: /usr/lib/python3.5/site-packages/pytz/zoneinfo/America/Toronto
    

    In that case there is not a zoneinfo sub dir in /usr/lib/python3.5/site-packages/pytz. But on the same machine this works fine..

    >>> pytz.timezone('America/Toronto')
    <DstTzInfo 'America/Toronto' LMT-1 day, 18:42:00 STD>
    
    opened by mayfield 14
  • _get_unix_timezone incorrect timezone parsing on Amazon Linux AMI release 2018.03

    _get_unix_timezone incorrect timezone parsing on Amazon Linux AMI release 2018.03

    The following happens on Amazon Linux AMI release 2018.03 with pendulum 2.0.0 (but also with 1.5.1):

    Python 3.4.8 (default, Apr 25 2018, 23:50:36)
    [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from pendulum.tz.local_timezone import _get_unix_timezone
    >>> _get_unix_timezone()
    Traceback (most recent call last):
      File "/home/dmitrii/.local/lib/python3.4/site-packages/pendulum/tz/zoneinfo/reader.py", line 49, in read_for
        file_path = pytzdata.tz_path(timezone)
      File "/usr/local/lib/python3.4/site-packages/pytzdata/__init__.py", line 74, in tz_path
        raise TimezoneNotFound('Timezone {} not found at {}'.format(name, filepath))
    pytzdata.exceptions.TimezoneNotFound: Timezone /usr/share/zoneinfo/Europe/Zurich not found at /usr/local/lib/python3.4/site-packages/pytzdata/zoneinfo/usr/share/zoneinfo/Europe/Zurich
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/dmitrii/.local/lib/python3.4/site-packages/pendulum/tz/local_timezone.py", line 206, in _get_unix_timezone
        return Timezone(etctz.replace(' ', '_'))
      File "/home/dmitrii/.local/lib/python3.4/site-packages/pendulum/tz/timezone.py", line 30, in __init__
        tz = read(name, extend=extended)
      File "/home/dmitrii/.local/lib/python3.4/site-packages/pendulum/tz/zoneinfo/__init__.py", line 9, in read
        return Reader(extend=extend).read_for(name)
      File "/home/dmitrii/.local/lib/python3.4/site-packages/pendulum/tz/zoneinfo/reader.py", line 51, in read_for
        raise InvalidTimezone(timezone)
    pendulum.tz.zoneinfo.exceptions.InvalidTimezone: Invalid timezone "/usr/share/zoneinfo/Europe/Zurich"
    

    The issue seems to be that _get_unix_timezone is unable to parse the string 'ZONE="/usr/share/zoneinfo/Europe/Zurich"\n which is returned when the zonefile is read.

    I think the issue is here that you expect there Europe/Zurich.

    opened by Dmitrii-I 13
  • Can't install pendulum with pip install -t

    Can't install pendulum with pip install -t

    Pendulum package is missing when installed with pip install -t

    ~/tmp> pip install -t lib pendulum
    Collecting pendulum
    Collecting pytz (from pendulum)
      Using cached pytz-2016.6.1-py2.py3-none-any.whl
    Collecting tzlocal (from pendulum)
    Collecting python-dateutil (from pendulum)
      Using cached python_dateutil-2.5.3-py2.py3-none-any.whl
    Collecting six>=1.5 (from python-dateutil->pendulum)
      Using cached six-1.10.0-py2.py3-none-any.whl
    Installing collected packages: pytz, tzlocal, six, python-dateutil, pendulum
    Successfully installed pendulum python-dateutil-2.5.3 pytz-2016.6.1 six-1.10.0 tzlocal-1.2.2
    
    ~/tmp> ls -l lib/
    total 64
    drwxrwxr-x 1 lauris lauris   276 Aug 17 17:41 dateutil
    drwxrwxr-x 1 lauris lauris   154 Aug 17 17:41 python_dateutil-2.5.3.dist-info
    drwxrwxr-x 1 lauris lauris   272 Aug 17 17:41 pytz
    drwxrwxr-x 1 lauris lauris   154 Aug 17 17:41 pytz-2016.6.1.dist-info
    drwxrwxr-x 1 lauris lauris   138 Aug 17 17:41 six-1.10.0.dist-info
    -rw-rw-r-- 1 lauris lauris 30098 Aug 17 17:41 six.py
    -rw-rw-r-- 1 lauris lauris 29545 Aug 17 17:41 six.pyc
    drwxrwxr-x 1 lauris lauris   254 Aug 17 17:41 tzlocal
    drwxrwxr-x 1 lauris lauris   154 Aug 17 17:41 tzlocal-1.2.2.dist-info
    
    ~/tmp> pip --version
    pip 8.1.2 from /usr/lib/python2.7/site-packages (python 2.7)
    
    opened by alekna 13
  • Incorrect formatting inside of f-string

    Incorrect formatting inside of f-string

    datetime:

    >>> import datetime
    >>> now = datetime.datetime.now()
    >>> f'{now:%H:%M %d.%m.%Y}'
    '15:39 16.05.2018'
    

    pendulum 2.0.1:

    >>> import pendulum
    >>> now = pendulum.now()
    >>> f'{now:%H:%M %d.%m.%Y}'
    '%15:%5 %3.%39.%2018'
    
    bug formatting 
    opened by Cykooz 12
  • pendulum object has no attribute 'translate'.

    pendulum object has no attribute 'translate'.

    I am using apache airflow 1.10 and the insallation of airflow also installed pendulam. So while running the job it throws an error like pendulum object has no attribute 'translate'. i am using mysql

    opened by lijoev 11
  • Release 3.0.0a1

    Release 3.0.0a1

    Added

    • Added new testing helpers to time travel. #626

    Changed

    • Dropped support for Python 2.7, 3.5 and 3.6. #569
    • The Timezone class now relies on the native zoneinfo.ZoneInfo class. #569
    • Renamed the Period class to Interval. #676
    • Renamed the period helper to interval. #676
    • Removed existing testing helpers: test() and set_test_now(). #626

    Locales

    • Added the sk locale. #575
    • Added the ja locale. #610
    • Added the he locale. #585
    • Added the sv locale. #562
    Release 
    opened by sdispater 0
  • Mypy improvement

    Mypy improvement

    Pull Request Check List

    • [ ] Added tests for changed code. Not needed
    • [ ] Updated documentation for changed code. No changes require documenting

    Mypy 0.990 added show_error_codes as enabled by default and our # type: ignore comments had wrong codes which caused a failure in #674.

    Second commit moves mypy usage away from pre-commit, since when it's being run from pre-commit, it might miss some typing issues coming from dependencies. See https://github.com/python-poetry/cleo/pull/254#issuecomment-1267690650

    opened by Secrus 0
  • arithmetic calculation of datetime is not correct if a month has 31 days

    arithmetic calculation of datetime is not correct if a month has 31 days

    • [x] I am on the latest Pendulum version.
    • [x] I have searched the issues of this repo and believe that this is not a duplicate.
    • OS version and name: Linux 5.10.109-104.500.amzn2.x86_64 (AWS EC2)
    • Pendulum version: 2.1.2

    Issue

    When calculating datetime A-B+B, I can't get A. Please see below. (If A is a month what has 31 days)

    from pendulum import datetime
    datetime(2022, 11, 10, 0, 30, tz='Asis/Seoul') - datetime(2022, 10, 10, 1, 30, tz='Asis/Seoul') + datetime(2022, 10,10, 1, 30, tz='Asis/Seoul')
    # DateTime(2022, 11, 11, 0, 30, 0, tzinfo=Timezone('Asia/Seoul'))
    # Expected value : DateTime(2022, 11, 10, 0, 30, 0, tzinfo=Timezone('Asia/Seoul'))
    

    But I can get expected datetime if A is month what has 30 days.

    from pendulum import datetime
    datetime(2022, 10, 10, 0, 30, tz='Asis/Seoul') - datetime(2022, 9, 10, 1, 30, tz='Asis/Seoul') + datetime(2022, 9, 10, 1, 30, tz='Asis/Seoul')
    # DateTime(2022, 10, 10, 0, 30, 0, tzinfo=Timezone('Asia/Seoul'))
    
    opened by wizneo 0
  • Fix typing of Timezone and ZoneInfo

    Fix typing of Timezone and ZoneInfo

    Currently the method used to import zoneinfo leaves it typed as Any in mypy and Unknown in pyright. This PR updates pendulum.utils._compat to inform type checkers of the correct type information for zoneinfo while leaving the import mechanism the same during runtime. With Timezone having the correct type info from ZoneInfo, a few more type errors surfaced which I took care of either by adding/removing # type: ignore or adding/removing cast() calls. Since no logic has changed at runtime, no unit tests were added.

    opened by bryanforbes 0
  • Automatically changes the timezone when adding days

    Automatically changes the timezone when adding days

    • [x] I am on the latest Pendulum version.
    • [x] I have searched the issues of this repo and believe that this is not a duplicate.
    • OS version and name: MacOS 13.0 Ventura
    • Pendulum version: 2.1.2

    Issue

    Pendulum automatically changes timezone when adding days.

    tz = 'America/Los_Angeles'
    now = pendulum.now(tz).set(hour=9, minute=0, second=0, microsecond=0)
    
    print(now)  # 2022-11-01T09:00:00-07:00
    print(now.add(days=6))  # 2022-11-07T09:00:00-08:00
    

    You can see that it properly adds 6 days, but then however changes the timezone from -07:00 to -08:00 while keeping the same hour.

    The same behaviour has been confirmed in AWS Lambda py39 environment.

    Adding minutes produces a different outcome:

    print(now.add(minutes=6 * 24 * 60))  # 2022-11-07T08:00:00-08:00
    
    opened by vladmiller 0
Releases(3.0.0a1)
Owner
Sébastien Eustace
Software engineer, proud pythonista, open source lover. Creator of the Poetry package manager and the datetime library Pendulum.
Sébastien Eustace
Delorean: Time Travel Made Easy

Delorean: Time Travel Made Easy Delorean is a library for clearing up the inconvenient truths that arise dealing with datetimes in Python. Understandi

Mahdi Yusuf 1.8k Nov 16, 2022
PyTime is an easy-use Python module which aims to operate date/time/datetime by string.

PyTime PyTime is an easy-use Python module which aims to operate date/time/datetime by string. PyTime allows you using nonregular datetime string to g

Sinux 146 Nov 5, 2022
darts is a Python library for easy manipulation and forecasting of time series.

A python library for easy manipulation and forecasting of time series.

Unit8 5k Nov 19, 2022
A simple digital clock made with the help of python

Digital-Clock ⏰ Description ?? ✔️ A simple digital clock made with the help of python. The code is easy to understand and implement. With this reposit

Mohit 0 Dec 10, 2021
A Python 3 library for parsing human-written times and dates

Chronyk A small Python 3 library containing some handy tools for handling time, especially when it comes to interfacing with those pesky humans. Featu

Felix Wiegand 340 Oct 30, 2022
Useful extensions to the standard Python datetime features

dateutil - powerful extensions to datetime The dateutil module provides powerful extensions to the standard datetime module, available in Python. Inst

null 1.9k Nov 20, 2022
A Python library for dealing with dates

moment A Python library for dealing with dates/times. Inspired by Moment.js and Kenneth Reitz's Requests library. Ideas were also taken from the Times

Zach Williams 708 Nov 8, 2022
Friendly Python Dates

When.py: Friendly Dates and Times Production: Development: User-friendly functions to help perform common date and time actions. Usage To get the syst

Andy Dirnberger 191 Oct 14, 2022
Better dates & times for Python

Arrow: Better dates & times for Python Arrow is a Python library that offers a sensible and human-friendly approach to creating, manipulating, formatt

Arrow 8.1k Nov 23, 2022
python parser for human readable dates

Python parser for human readable dates Key Features • How To Use • Installation • Common use cases • You may also like... • License Key Features Suppo

Scrapinghub 2.1k Nov 24, 2022
pytz Python historical timezone library and database

pytz Brings the IANA tz database into Python. This library allows accurate and cross platform timezone calculations. pytz contains generated code, and

Stub 229 Nov 21, 2022
Generate and work with holidays in Python

python-holidays A fast, efficient Python library for generating country, province and state specific sets of holidays on the fly. It aims to make dete

Maurizio Montel 854 Nov 20, 2022
A Python module that tries to figure out what your local timezone is

tzlocal This Python module returns a tzinfo object with the local timezone information under Unix and Windows. It requires either Python 3.9+ or the b

Lennart Regebro 160 Sep 9, 2022
A simple in-process python scheduler library, designed to be integrated seamlessly with the `datetime` standard library.

scheduler A simple in-process python scheduler library, designed to be integrated seamlessly with the datetime standard library. Due to the support of

null 22 Nov 15, 2022
Make Python datetime formatting human readable

Make Python datetime formatting human readable

James Timmins 0 Oct 3, 2021
A datetime parser in Python by Ari24-cb24 and NekoFantic

datetimeparser A datetime parser in Python by Ari24-cb24 and NekoFantic V 1.0 Erinnerung für den Parser Auf falsche Eingaben überprüfen Liste an Event

AriDevelopment 12 Oct 28, 2022
Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy

orjson orjson is a fast, correct JSON library for Python. It benchmarks as the fastest Python library for JSON and is more correct than the standard j

null 3.9k Nov 19, 2022
Datetimes for Humans™

Maya: Datetimes for Humans™ Datetimes are very frustrating to work with in Python, especially when dealing with different locales on different systems

Timo Furrer 3.4k Nov 24, 2022
Datetimes for Humans™

Maya: Datetimes for Humans™ Datetimes are very frustrating to work with in Python, especially when dealing with different locales on different systems

Timo Furrer 3.4k Nov 16, 2022
A Screen Translator/OCR Translator made by using Python and Tesseract, the user interface are made using Tkinter. All code written in python.

About An OCR translator tool. Made by me by utilizing Tesseract, compiled to .exe using pyinstaller. I made this program to learn more about python. I

Fauzan F A 35 Nov 15, 2022