Skip to content

Commit

Permalink
move impl to polars-time
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcoGorelli committed Apr 7, 2024
1 parent 9a559ea commit 79d87d2
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use polars_core::chunked_array::ops::arity::binary_elementwise_values;
use polars_core::prelude::*;
use polars_time::business_day_count_impl;

pub(super) fn business_day_count(s: &[Series]) -> PolarsResult<Series> {
let start = &s[0];
Expand All @@ -16,7 +17,7 @@ pub(super) fn business_day_count(s: &[Series]) -> PolarsResult<Series> {
(_, 1) => {
if let Some(end_date) = end_dates.get(0) {
start_dates.apply_values(|start_date| {
impl_business_day_count(
business_day_count_impl(
start_date,
end_date,
&week_mask,
Expand All @@ -30,7 +31,7 @@ pub(super) fn business_day_count(s: &[Series]) -> PolarsResult<Series> {
(1, _) => {
if let Some(start_date) = start_dates.get(0) {
end_dates.apply_values(|end_date| {
impl_business_day_count(
business_day_count_impl(
start_date,
end_date,
&week_mask,
Expand All @@ -42,7 +43,7 @@ pub(super) fn business_day_count(s: &[Series]) -> PolarsResult<Series> {
}
},
_ => binary_elementwise_values(start_dates, end_dates, |start_date, end_date| {
impl_business_day_count(
business_day_count_impl(
start_date,
end_date,
&week_mask,
Expand All @@ -52,48 +53,3 @@ pub(super) fn business_day_count(s: &[Series]) -> PolarsResult<Series> {
};
Ok(out.into_series())
}

/// Ported from:
/// https://github.com/numpy/numpy/blob/e59c074842e3f73483afa5ddef031e856b9fd313/numpy/_core/src/multiarray/datetime_busday.c#L355-L433
fn impl_business_day_count(
mut start_date: i32,
mut end_date: i32,
week_mask: &[bool; 7],
n_business_days_in_week_mask: i32,
) -> i32 {
let swapped = start_date > end_date;
if swapped {
(start_date, end_date) = (end_date, start_date);
start_date += 1;
end_date += 1;
}

let mut start_weekday = weekday(start_date);
let diff = end_date - start_date;
let whole_weeks = diff / 7;
let mut count = 0;
count += whole_weeks * n_business_days_in_week_mask;
start_date += whole_weeks * 7;
while start_date < end_date {
if unsafe { *week_mask.get_unchecked(start_weekday) } {
count += 1;
}
start_date += 1;
start_weekday += 1;
if start_weekday >= 7 {
start_weekday = 0;
}
}
if swapped {
-count
} else {
count
}
}

pub(crate) fn weekday(x: i32) -> usize {
// the first modulo might return a negative number, so we add 7 and take
// the modulo again so we're sure we have something between 0 (Monday)
// and 6 (Sunday)
(((x - 4) % 7 + 7) % 7) as usize
}
45 changes: 45 additions & 0 deletions crates/polars-time/src/business.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/// Ported from:
/// https://github.com/numpy/numpy/blob/e59c074842e3f73483afa5ddef031e856b9fd313/numpy/_core/src/multiarray/datetime_busday.c#L355-L433
#[doc(hidden)]
pub fn business_day_count_impl(
mut start_date: i32,
mut end_date: i32,
week_mask: &[bool; 7],
n_business_days_in_week_mask: i32,
) -> i32 {
let swapped = start_date > end_date;
if swapped {
(start_date, end_date) = (end_date, start_date);
start_date += 1;
end_date += 1;
}

let mut start_weekday = weekday(start_date);
let diff = end_date - start_date;
let whole_weeks = diff / 7;
let mut count = 0;
count += whole_weeks * n_business_days_in_week_mask;
start_date += whole_weeks * 7;
while start_date < end_date {
if unsafe { *week_mask.get_unchecked(start_weekday) } {
count += 1;
}
start_date += 1;
start_weekday += 1;
if start_weekday >= 7 {
start_weekday = 0;
}
}
if swapped {
-count
} else {
count
}
}

pub(crate) fn weekday(x: i32) -> usize {
// the first modulo might return a negative number, so we add 7 and take
// the modulo again so we're sure we have something between 0 (Monday)
// and 6 (Sunday)
(((x - 4) % 7 + 7) % 7) as usize
}
2 changes: 2 additions & 0 deletions crates/polars-time/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
mod base_utc_offset;
mod business;
pub mod chunkedarray;
mod date_range;
mod dst_offset;
Expand All @@ -16,6 +17,7 @@ mod windows;

#[cfg(feature = "timezones")]
pub use base_utc_offset::*;
pub use business::*;
pub use date_range::*;
#[cfg(feature = "timezones")]
pub use dst_offset::*;
Expand Down

0 comments on commit 79d87d2

Please sign in to comment.