Skip to main content

Business day utilities for Polars

Project description

Polars-business

polars-business

Business day utilities for Polars.

  • ✅ blazingly fast, written in Rust!
  • ✅ define your own custom holidays!
  • ✅ define your own custom weekend days!
  • ✅ works with Polars lazy execution!

Installation

First, you need to install Polars.

Then, you'll need to install polars-business:

pip install polars-business

Usage

  1. import polars_business
  2. use .bdt accessor on expressions

See Examples below!

Examples

Say we start with

from datetime import date

import polars as pl
import polars_business


df = pl.DataFrame(
    {"date": [date(2023, 4, 3), date(2023, 9, 1), date(2024, 1, 4)]}
)

Let's shift Date forwards by 5 days, excluding Saturday and Sunday:

result = df.with_columns(
    date_shifted=pl.col("date").bdt.offset_by('5bd')
)
print(result)
shape: (3, 2)
┌────────────┬──────────────┐
│ date       ┆ date_shifted │
│ ---        ┆ ---          │
│ date       ┆ date         │
╞════════════╪══════════════╡
│ 2023-04-03 ┆ 2023-04-10   │
│ 2023-09-01 ┆ 2023-09-08   │
│ 2024-01-04 ┆ 2024-01-11   │
└────────────┴──────────────┘

Let's shift Date forwards by 5 days, excluding Saturday and Sunday and UK holidays for 2023 and 2024:

import holidays

uk_holidays = holidays.country_holidays("UK", years=[2023, 2024])

result = df.with_columns(
    date_shifted=pl.col("date").bdt.advance_n_days(
      by='5bd',
      holidays=uk_holidays,
    )
)
print(result)
shape: (3, 2)
┌────────────┬──────────────┐
│ date       ┆ date_shifted │
│ ---        ┆ ---          │
│ date       ┆ date         │
╞════════════╪══════════════╡
│ 2023-04-03 ┆ 2023-04-11   │
│ 2023-09-01 ┆ 2023-09-08   │
│ 2024-01-04 ┆ 2024-01-11   │
└────────────┴──────────────┘

Let's shift Date forwards by 5 days, excluding only Sunday:

result = df.with_columns(
    date_shifted=pl.col("date").bdt.offset_by(
      by='5bd',
      weekend=['Sun'],
    )
)
print(result)
shape: (3, 2)
┌────────────┬──────────────┐
│ date       ┆ date_shifted │
│ ---        ┆ ---          │
│ date       ┆ date         │
╞════════════╪══════════════╡
│ 2023-04-03 ┆ 2023-04-08   │
│ 2023-09-01 ┆ 2023-09-07   │
│ 2024-01-04 ┆ 2024-01-10   │
└────────────┴──────────────┘

What to expected

The following will hopefully come relatively soon:

  • support for rolling forwards/backwards to the next valid business date (if not already on one)
  • calculate the number of business days between two dates (like np.busday_count)

Ideas for future development:

  • business date range

Benchmarks

Note: take these with a grain of salt.

But I think they demonstrate:

  • that polars-business is on-par with numpy for performance,
  • that polars-business is at least an order of magnitude faster than pandas.

Note that this is single threaded performance. In common usage these will likely run in parallel.

The following timings can be verified using the perf.py script (note: lower is better):

Adding 17 business days to 1 million random dates (no holidays)

  • Polars-business 0.00656s
  • NumPy 0.00914s
  • pandas 0.08006s

Adding 17 business days to 1 million random dates (UK holidays for 2020-2023)

  • Polars-business 0.03771s
  • NumPy 0.04077s
  • pandas: omitted as it's not vectorised and throws a PerformanceWarning

Adding 17 business days to 1 million random dates (with 'Friday' and 'Saturday' as weekend)

  • Polars-business 0.0108s
  • NumPy 0.01057s
  • pandas: omitted as it's not vectorised and throws a PerformanceWarning

Adding 17 business days to 1 million random dates (with 'Friday' and 'Saturday' as weekend, and UK holidays for 2020-2023)

  • Polars-business 0.0371s
  • NumPy 0.03841s
  • pandas: omitted as it's not vectorised and throws a PerformanceWarning

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

polars_business-0.1.25.tar.gz (16.5 kB view hashes)

Uploaded Source

Built Distributions

polars_business-0.1.25-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (5.4 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

polars_business-0.1.25-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl (4.9 MB view hashes)

Uploaded PyPy manylinux: glibc 2.12+ i686

polars_business-0.1.25-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

polars_business-0.1.25-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (5.4 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

polars_business-0.1.25-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (6.1 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

polars_business-0.1.25-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (4.5 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

polars_business-0.1.25-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl (4.9 MB view hashes)

Uploaded PyPy manylinux: glibc 2.12+ i686

polars_business-0.1.25-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

polars_business-0.1.25-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (5.4 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

polars_business-0.1.25-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (6.1 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

polars_business-0.1.25-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (4.5 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

polars_business-0.1.25-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl (4.9 MB view hashes)

Uploaded PyPy manylinux: glibc 2.12+ i686

polars_business-0.1.25-cp312-none-win_amd64.whl (2.9 MB view hashes)

Uploaded CPython 3.12 Windows x86-64

polars_business-0.1.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

polars_business-0.1.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl (5.4 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ s390x

polars_business-0.1.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (6.1 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ppc64le

polars_business-0.1.25-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (4.5 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARMv7l

polars_business-0.1.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.4 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

polars_business-0.1.25-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl (4.9 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.12+ i686

polars_business-0.1.25-cp311-none-win_amd64.whl (2.9 MB view hashes)

Uploaded CPython 3.11 Windows x86-64

polars_business-0.1.25-cp311-none-win32.whl (2.6 MB view hashes)

Uploaded CPython 3.11 Windows x86

polars_business-0.1.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

polars_business-0.1.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl (5.4 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ s390x

polars_business-0.1.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (6.1 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ppc64le

polars_business-0.1.25-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (4.5 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARMv7l

polars_business-0.1.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.4 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

polars_business-0.1.25-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl (4.9 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.12+ i686

polars_business-0.1.25-cp311-cp311-macosx_11_0_arm64.whl (2.9 MB view hashes)

Uploaded CPython 3.11 macOS 11.0+ ARM64

polars_business-0.1.25-cp311-cp311-macosx_10_12_x86_64.whl (3.2 MB view hashes)

Uploaded CPython 3.11 macOS 10.12+ x86-64

polars_business-0.1.25-cp310-none-win_amd64.whl (2.9 MB view hashes)

Uploaded CPython 3.10 Windows x86-64

polars_business-0.1.25-cp310-none-win32.whl (2.6 MB view hashes)

Uploaded CPython 3.10 Windows x86

polars_business-0.1.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

polars_business-0.1.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl (5.4 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ s390x

polars_business-0.1.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (6.1 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ppc64le

polars_business-0.1.25-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (4.5 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARMv7l

polars_business-0.1.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.4 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

polars_business-0.1.25-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl (4.9 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.12+ i686

polars_business-0.1.25-cp310-cp310-macosx_11_0_arm64.whl (2.9 MB view hashes)

Uploaded CPython 3.10 macOS 11.0+ ARM64

polars_business-0.1.25-cp310-cp310-macosx_10_12_x86_64.whl (3.2 MB view hashes)

Uploaded CPython 3.10 macOS 10.12+ x86-64

polars_business-0.1.25-cp39-none-win_amd64.whl (2.9 MB view hashes)

Uploaded CPython 3.9 Windows x86-64

polars_business-0.1.25-cp39-none-win32.whl (2.6 MB view hashes)

Uploaded CPython 3.9 Windows x86

polars_business-0.1.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

polars_business-0.1.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl (5.4 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ s390x

polars_business-0.1.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (6.1 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ppc64le

polars_business-0.1.25-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (4.5 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARMv7l

polars_business-0.1.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.4 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

polars_business-0.1.25-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl (4.9 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.12+ i686

polars_business-0.1.25-cp38-none-win_amd64.whl (2.9 MB view hashes)

Uploaded CPython 3.8 Windows x86-64

polars_business-0.1.25-cp38-none-win32.whl (2.6 MB view hashes)

Uploaded CPython 3.8 Windows x86

polars_business-0.1.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

polars_business-0.1.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl (5.4 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ s390x

polars_business-0.1.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (6.1 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ppc64le

polars_business-0.1.25-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (4.5 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARMv7l

polars_business-0.1.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.4 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

polars_business-0.1.25-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl (4.9 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.12+ i686

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page