polars-df 0.21.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/Cargo.lock +1 -1
  4. data/ext/polars/Cargo.toml +7 -1
  5. data/ext/polars/src/conversion/mod.rs +92 -4
  6. data/ext/polars/src/exceptions.rs +1 -0
  7. data/ext/polars/src/expr/array.rs +73 -4
  8. data/ext/polars/src/expr/binary.rs +26 -1
  9. data/ext/polars/src/expr/bitwise.rs +39 -0
  10. data/ext/polars/src/expr/categorical.rs +20 -0
  11. data/ext/polars/src/expr/datatype.rs +24 -1
  12. data/ext/polars/src/expr/datetime.rs +58 -0
  13. data/ext/polars/src/expr/general.rs +84 -5
  14. data/ext/polars/src/expr/list.rs +24 -0
  15. data/ext/polars/src/expr/meta.rs +11 -0
  16. data/ext/polars/src/expr/mod.rs +1 -0
  17. data/ext/polars/src/expr/name.rs +8 -0
  18. data/ext/polars/src/expr/rolling.rs +20 -0
  19. data/ext/polars/src/expr/string.rs +59 -0
  20. data/ext/polars/src/expr/struct.rs +9 -1
  21. data/ext/polars/src/functions/io.rs +19 -0
  22. data/ext/polars/src/functions/lazy.rs +4 -0
  23. data/ext/polars/src/lazyframe/general.rs +51 -0
  24. data/ext/polars/src/lib.rs +119 -10
  25. data/ext/polars/src/map/dataframe.rs +2 -2
  26. data/ext/polars/src/map/series.rs +1 -1
  27. data/ext/polars/src/series/aggregation.rs +44 -0
  28. data/ext/polars/src/series/general.rs +64 -4
  29. data/lib/polars/array_expr.rb +382 -3
  30. data/lib/polars/array_name_space.rb +281 -0
  31. data/lib/polars/binary_expr.rb +67 -0
  32. data/lib/polars/binary_name_space.rb +43 -0
  33. data/lib/polars/cat_expr.rb +224 -0
  34. data/lib/polars/cat_name_space.rb +138 -0
  35. data/lib/polars/config.rb +2 -2
  36. data/lib/polars/convert.rb +6 -6
  37. data/lib/polars/data_frame.rb +684 -19
  38. data/lib/polars/data_type_expr.rb +52 -0
  39. data/lib/polars/data_types.rb +14 -2
  40. data/lib/polars/date_time_expr.rb +251 -0
  41. data/lib/polars/date_time_name_space.rb +299 -0
  42. data/lib/polars/expr.rb +1213 -180
  43. data/lib/polars/functions/datatype.rb +21 -0
  44. data/lib/polars/functions/lazy.rb +13 -0
  45. data/lib/polars/io/csv.rb +1 -1
  46. data/lib/polars/io/json.rb +4 -4
  47. data/lib/polars/io/ndjson.rb +4 -4
  48. data/lib/polars/io/parquet.rb +27 -5
  49. data/lib/polars/lazy_frame.rb +936 -20
  50. data/lib/polars/list_expr.rb +196 -4
  51. data/lib/polars/list_name_space.rb +201 -4
  52. data/lib/polars/meta_expr.rb +64 -0
  53. data/lib/polars/name_expr.rb +36 -0
  54. data/lib/polars/schema.rb +79 -3
  55. data/lib/polars/selector.rb +72 -0
  56. data/lib/polars/selectors.rb +3 -3
  57. data/lib/polars/series.rb +1051 -54
  58. data/lib/polars/string_expr.rb +411 -6
  59. data/lib/polars/string_name_space.rb +722 -49
  60. data/lib/polars/struct_expr.rb +103 -0
  61. data/lib/polars/struct_name_space.rb +19 -1
  62. data/lib/polars/utils/various.rb +18 -1
  63. data/lib/polars/utils.rb +5 -1
  64. data/lib/polars/version.rb +1 -1
  65. data/lib/polars.rb +2 -0
  66. metadata +4 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f70a1d0c71919e3a30fdb634d0830b9fb1c10e1e7cffeef7ce708a231e0dd17
4
- data.tar.gz: 58c9913f4fd47fbde9ad68ac7ddbdd64afc441941f623b3b407295783d14644c
3
+ metadata.gz: a19860350cc2b97401611c848072bace63f15188d8b43289cca12d6adcf7593c
4
+ data.tar.gz: 01565f74f8b41286214c22e2016f45e0da05a8c9ce610f7cb3dd3616292f185b
5
5
  SHA512:
6
- metadata.gz: 71dd11888467ed867894e7990718fcd5535d433d64db2340442a9f0f84c082560a97bb4de0bfb609f3dfd1a2988c9b7dcff0aef85cfa78670af0ed3f34994840
7
- data.tar.gz: 363d53b6257f4144dd341916d3d103d8197469886abc836c0c184281191d16cfe9140207d4643008adb6118aafd2bd6f8fefc99962f49642409720db79a4b114
6
+ metadata.gz: 391989a65c5a2c5b96ad05f9b9f0553c97153133a3f522ea8d77173b6f9fb3e9ca3838f453a2a750b158a8f0b86a0ffad62468789f84a993e16005342d6a8b14
7
+ data.tar.gz: cf846b8cfcd4f44085a583b133f935f636764f1a440dcf4cd3c98b52a510066036b8565cb8ac1089f5cdb433c4dcab05b9325772d97e3d48ad7ebd1de9aeadd8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## 0.21.1 (2025-08-18)
2
+
3
+ - Added `read_parquet_metadata` method to `Polars`
4
+ - Added more methods to `Series` and `Expr`
5
+ - Added more methods to `DataFrame` and `LazyFrame`
6
+ - Added more methods to `ArrayExpr` and `ArrayNameSpace`
7
+ - Added more methods to `BinaryExpr` and `BinaryNameSpace`
8
+ - Added more methods to `CatExpr` and `CatNameSpace`
9
+ - Added more methods to `DateTimeExpr` ane `DateTimeNameSpace`
10
+ - Added more methods to `ListExpr` and `ListNameSpace`
11
+ - Added more methods to `MetaExpr`
12
+ - Added more methods to `NameExpr`
13
+ - Added more methods to `StringExpr` and `StringNameSpace`
14
+ - Added more methods to `StructExpr` and `StructNameSpace`
15
+ - Fixed `subset` option for `drop_nulls` method
16
+
1
17
  ## 0.21.0 (2025-08-03)
2
18
 
3
19
  - Updated Polars to 0.50.0
data/Cargo.lock CHANGED
@@ -1654,7 +1654,7 @@ dependencies = [
1654
1654
 
1655
1655
  [[package]]
1656
1656
  name = "polars"
1657
- version = "0.21.0"
1657
+ version = "0.21.1"
1658
1658
  dependencies = [
1659
1659
  "ahash",
1660
1660
  "bytes",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "polars"
3
- version = "0.21.0"
3
+ version = "0.21.1"
4
4
  license = "MIT"
5
5
  authors = ["Andrew Kane <andrew@ankane.org>"]
6
6
  edition = "2024"
@@ -37,11 +37,13 @@ features = [
37
37
  "arg_where",
38
38
  "array_any_all",
39
39
  "array_count",
40
+ "array_to_struct",
40
41
  "asof_join",
41
42
  "avro",
42
43
  "aws",
43
44
  "azure",
44
45
  "binary_encoding",
46
+ "bitwise",
45
47
  "business",
46
48
  "cloud",
47
49
  "concat_str",
@@ -65,12 +67,16 @@ features = [
65
67
  "find_many",
66
68
  "fmt",
67
69
  "gcp",
70
+ "hist",
68
71
  "http",
72
+ "iejoin",
73
+ "index_of",
69
74
  "interpolate",
70
75
  "interpolate_by",
71
76
  "ipc",
72
77
  "ipc_streaming",
73
78
  "is_between",
79
+ "is_close",
74
80
  "is_first_distinct",
75
81
  "is_in",
76
82
  "is_last_distinct",
@@ -21,6 +21,7 @@ use polars::io::cloud::CloudOptions;
21
21
  use polars::prelude::deletion::DeletionFilesList;
22
22
  use polars::prelude::*;
23
23
  use polars::series::ops::NullBehavior;
24
+ use polars_core::schema::iceberg::IcebergSchema;
24
25
  use polars_core::utils::arrow::array::Array;
25
26
  use polars_core::utils::materialize_dyn_int;
26
27
  use polars_plan::dsl::ScanSources;
@@ -30,6 +31,7 @@ use polars_utils::total_ord::{TotalEq, TotalHash};
30
31
  use crate::file::{RubyScanSourceInput, get_ruby_scan_source_input};
31
32
  use crate::object::OBJECT_NAME;
32
33
  use crate::rb_modules::series;
34
+ use crate::utils::to_rb_err;
33
35
  use crate::{RbDataFrame, RbLazyFrame, RbPolarsErr, RbResult, RbSeries, RbTypeError, RbValueError};
34
36
 
35
37
  pub(crate) fn slice_extract_wrapped<T>(slice: &[Wrap<T>]) -> &[T] {
@@ -524,6 +526,12 @@ impl TryConvert for Wrap<Schema> {
524
526
  }
525
527
  }
526
528
 
529
+ impl TryConvert for Wrap<ArrowSchema> {
530
+ fn try_convert(_ob: Value) -> RbResult<Self> {
531
+ todo!();
532
+ }
533
+ }
534
+
527
535
  impl TryConvert for Wrap<ScanSources> {
528
536
  fn try_convert(ob: Value) -> RbResult<Self> {
529
537
  let list = RArray::try_convert(ob)?;
@@ -979,6 +987,22 @@ impl TryConvert for Wrap<RankMethod> {
979
987
  }
980
988
  }
981
989
 
990
+ impl TryConvert for Wrap<Roll> {
991
+ fn try_convert(ob: Value) -> RbResult<Self> {
992
+ let parsed = match String::try_convert(ob)?.as_str() {
993
+ "raise" => Roll::Raise,
994
+ "forward" => Roll::Forward,
995
+ "backward" => Roll::Backward,
996
+ v => {
997
+ return Err(RbValueError::new_err(format!(
998
+ "`roll` must be one of {{'raise', 'forward', 'backward'}}, got {v}",
999
+ )));
1000
+ }
1001
+ };
1002
+ Ok(Wrap(parsed))
1003
+ }
1004
+ }
1005
+
982
1006
  impl TryConvert for Wrap<TimeUnit> {
983
1007
  fn try_convert(ob: Value) -> RbResult<Self> {
984
1008
  let parsed = match String::try_convert(ob)?.as_str() {
@@ -1270,6 +1294,23 @@ impl TryConvert for RbCompatLevel {
1270
1294
  }
1271
1295
  }
1272
1296
 
1297
+ impl TryConvert for Wrap<UnicodeForm> {
1298
+ fn try_convert(ob: Value) -> RbResult<Self> {
1299
+ let parsed = match String::try_convert(ob)?.as_str() {
1300
+ "NFC" => UnicodeForm::NFC,
1301
+ "NFKC" => UnicodeForm::NFKC,
1302
+ "NFD" => UnicodeForm::NFD,
1303
+ "NFKD" => UnicodeForm::NFKD,
1304
+ v => {
1305
+ return Err(RbValueError::new_err(format!(
1306
+ "`form` must be one of {{'NFC', 'NFKC', 'NFD', 'NFKD'}}, got {v}",
1307
+ )));
1308
+ }
1309
+ };
1310
+ Ok(Wrap(parsed))
1311
+ }
1312
+ }
1313
+
1273
1314
  impl TryConvert for Wrap<Option<TimeZone>> {
1274
1315
  fn try_convert(ob: Value) -> RbResult<Self> {
1275
1316
  let tz = Option::<Wrap<PlSmallStr>>::try_convert(ob)?;
@@ -1313,13 +1354,60 @@ impl TryConvert for Wrap<MissingColumnsPolicy> {
1313
1354
  }
1314
1355
 
1315
1356
  impl TryConvert for Wrap<ColumnMapping> {
1316
- fn try_convert(_ob: Value) -> RbResult<Self> {
1317
- todo!()
1357
+ fn try_convert(ob: Value) -> RbResult<Self> {
1358
+ let (column_mapping_type, ob) = <(String, Value)>::try_convert(ob)?;
1359
+
1360
+ Ok(Wrap(match column_mapping_type.as_str() {
1361
+ "iceberg-column-mapping" => {
1362
+ let arrow_schema = Wrap::<ArrowSchema>::try_convert(ob)?;
1363
+ ColumnMapping::Iceberg(Arc::new(
1364
+ IcebergSchema::from_arrow_schema(&arrow_schema.0).map_err(to_rb_err)?,
1365
+ ))
1366
+ }
1367
+
1368
+ v => {
1369
+ return Err(RbValueError::new_err(format!(
1370
+ "unknown column mapping type: {v}"
1371
+ )));
1372
+ }
1373
+ }))
1318
1374
  }
1319
1375
  }
1320
1376
 
1321
1377
  impl TryConvert for Wrap<DeletionFilesList> {
1322
- fn try_convert(_ob: Value) -> RbResult<Self> {
1323
- todo!();
1378
+ fn try_convert(ob: Value) -> RbResult<Self> {
1379
+ let (deletion_file_type, ob) = <(String, Value)>::try_convert(ob)?;
1380
+
1381
+ Ok(Wrap(match deletion_file_type.as_str() {
1382
+ "iceberg-position-delete" => {
1383
+ let dict = RHash::try_convert(ob)?;
1384
+
1385
+ let mut out = PlIndexMap::new();
1386
+
1387
+ dict.foreach(|k: usize, v: RArray| {
1388
+ let files = v
1389
+ .into_iter()
1390
+ .map(|x| {
1391
+ let x = String::try_convert(x)?;
1392
+ Ok(x)
1393
+ })
1394
+ .collect::<RbResult<Arc<[String]>>>()?;
1395
+
1396
+ if !files.is_empty() {
1397
+ out.insert(k, files);
1398
+ }
1399
+
1400
+ Ok(ForEach::Continue)
1401
+ })?;
1402
+
1403
+ DeletionFilesList::IcebergPositionDelete(Arc::new(out))
1404
+ }
1405
+
1406
+ v => {
1407
+ return Err(RbValueError::new_err(format!(
1408
+ "unknown deletion file type: {v}"
1409
+ )));
1410
+ }
1411
+ }))
1324
1412
  }
1325
1413
  }
@@ -20,5 +20,6 @@ macro_rules! create_exception {
20
20
  create_exception!(RbTypeError, exception::type_error());
21
21
  create_exception!(RbValueError, exception::arg_error());
22
22
  create_exception!(RbOverflowError, exception::range_error());
23
+ create_exception!(RbIndexError, exception::index_error());
23
24
  create_exception!(ComputeError, rb_modules::compute_error());
24
25
  create_exception!(InvalidOperationError, rb_modules::invalid_operation_error());
@@ -1,20 +1,41 @@
1
+ use magnus::Value;
1
2
  use polars::prelude::*;
2
3
 
3
- use crate::RbExpr;
4
+ use crate::{RbExpr, RbPolarsErr, RbResult};
4
5
 
5
6
  impl RbExpr {
6
- pub fn array_max(&self) -> Self {
7
+ pub fn arr_len(&self) -> Self {
8
+ self.inner.clone().arr().len().into()
9
+ }
10
+
11
+ pub fn arr_max(&self) -> Self {
7
12
  self.inner.clone().arr().max().into()
8
13
  }
9
14
 
10
- pub fn array_min(&self) -> Self {
15
+ pub fn arr_min(&self) -> Self {
11
16
  self.inner.clone().arr().min().into()
12
17
  }
13
18
 
14
- pub fn array_sum(&self) -> Self {
19
+ pub fn arr_sum(&self) -> Self {
15
20
  self.inner.clone().arr().sum().into()
16
21
  }
17
22
 
23
+ pub fn arr_std(&self, ddof: u8) -> Self {
24
+ self.inner.clone().arr().std(ddof).into()
25
+ }
26
+
27
+ pub fn arr_var(&self, ddof: u8) -> Self {
28
+ self.inner.clone().arr().var(ddof).into()
29
+ }
30
+
31
+ pub fn arr_mean(&self) -> Self {
32
+ self.inner.clone().arr().mean().into()
33
+ }
34
+
35
+ pub fn arr_median(&self) -> Self {
36
+ self.inner.clone().arr().median().into()
37
+ }
38
+
18
39
  pub fn arr_unique(&self, maintain_order: bool) -> Self {
19
40
  if maintain_order {
20
41
  self.inner.clone().arr().unique_stable().into()
@@ -23,6 +44,10 @@ impl RbExpr {
23
44
  }
24
45
  }
25
46
 
47
+ pub fn arr_n_unique(&self) -> Self {
48
+ self.inner.clone().arr().n_unique().into()
49
+ }
50
+
26
51
  pub fn arr_to_list(&self) -> Self {
27
52
  self.inner.clone().arr().to_list().into()
28
53
  }
@@ -90,4 +115,48 @@ impl RbExpr {
90
115
  .count_matches(expr.inner.clone())
91
116
  .into()
92
117
  }
118
+
119
+ pub fn arr_to_struct(&self, name_gen: Option<Value>) -> Self {
120
+ if name_gen.is_some() {
121
+ todo!();
122
+ }
123
+ self.inner.clone().arr().to_struct(None).into()
124
+ }
125
+
126
+ pub fn arr_slice(
127
+ &self,
128
+ offset: &RbExpr,
129
+ length: Option<&RbExpr>,
130
+ as_array: bool,
131
+ ) -> RbResult<Self> {
132
+ let length = match length {
133
+ Some(i) => i.inner.clone(),
134
+ None => lit(i64::MAX),
135
+ };
136
+ Ok(self
137
+ .inner
138
+ .clone()
139
+ .arr()
140
+ .slice(offset.inner.clone(), length, as_array)
141
+ .map_err(RbPolarsErr::from)?
142
+ .into())
143
+ }
144
+
145
+ pub fn arr_tail(&self, n: &RbExpr, as_array: bool) -> RbResult<Self> {
146
+ Ok(self
147
+ .inner
148
+ .clone()
149
+ .arr()
150
+ .tail(n.inner.clone(), as_array)
151
+ .map_err(RbPolarsErr::from)?
152
+ .into())
153
+ }
154
+
155
+ pub fn arr_shift(&self, n: &RbExpr) -> Self {
156
+ self.inner.clone().arr().shift(n.inner.clone()).into()
157
+ }
158
+
159
+ pub fn arr_explode(&self) -> Self {
160
+ self.inner.clone().arr().explode().into()
161
+ }
93
162
  }
@@ -1,4 +1,5 @@
1
- use crate::RbExpr;
1
+ use crate::expr::datatype::RbDataTypeExpr;
2
+ use crate::{RbExpr, RbResult};
2
3
 
3
4
  impl RbExpr {
4
5
  pub fn bin_contains(&self, lit: &RbExpr) -> Self {
@@ -40,4 +41,28 @@ impl RbExpr {
40
41
  pub fn bin_base64_encode(&self) -> Self {
41
42
  self.inner.clone().binary().base64_encode().into()
42
43
  }
44
+
45
+ pub fn bin_reinterpret(&self, dtype: &RbDataTypeExpr, kind: String) -> RbResult<Self> {
46
+ use crate::RbValueError;
47
+
48
+ let is_little_endian = match kind.to_lowercase().as_str() {
49
+ "little" => true,
50
+ "big" => false,
51
+ _ => {
52
+ return Err(RbValueError::new_err(format!(
53
+ "Invalid endianness: {kind}. Valid values are \"little\" or \"big\"."
54
+ )));
55
+ }
56
+ };
57
+ Ok(self
58
+ .inner
59
+ .clone()
60
+ .binary()
61
+ .reinterpret(dtype.inner.clone(), is_little_endian)
62
+ .into())
63
+ }
64
+
65
+ pub fn bin_size_bytes(&self) -> Self {
66
+ self.inner.clone().binary().size_bytes().into()
67
+ }
43
68
  }
@@ -0,0 +1,39 @@
1
+ use crate::RbExpr;
2
+
3
+ impl RbExpr {
4
+ pub fn bitwise_count_ones(&self) -> Self {
5
+ self.inner.clone().bitwise_count_ones().into()
6
+ }
7
+
8
+ pub fn bitwise_count_zeros(&self) -> Self {
9
+ self.inner.clone().bitwise_count_zeros().into()
10
+ }
11
+
12
+ pub fn bitwise_leading_ones(&self) -> Self {
13
+ self.inner.clone().bitwise_leading_ones().into()
14
+ }
15
+
16
+ pub fn bitwise_leading_zeros(&self) -> Self {
17
+ self.inner.clone().bitwise_leading_zeros().into()
18
+ }
19
+
20
+ pub fn bitwise_trailing_ones(&self) -> Self {
21
+ self.inner.clone().bitwise_trailing_ones().into()
22
+ }
23
+
24
+ pub fn bitwise_trailing_zeros(&self) -> Self {
25
+ self.inner.clone().bitwise_trailing_zeros().into()
26
+ }
27
+
28
+ pub fn bitwise_and(&self) -> Self {
29
+ self.inner.clone().bitwise_and().into()
30
+ }
31
+
32
+ pub fn bitwise_or(&self) -> Self {
33
+ self.inner.clone().bitwise_or().into()
34
+ }
35
+
36
+ pub fn bitwise_xor(&self) -> Self {
37
+ self.inner.clone().bitwise_xor().into()
38
+ }
39
+ }
@@ -4,4 +4,24 @@ impl RbExpr {
4
4
  pub fn cat_get_categories(&self) -> Self {
5
5
  self.inner.clone().cat().get_categories().into()
6
6
  }
7
+
8
+ pub fn cat_len_bytes(&self) -> Self {
9
+ self.inner.clone().cat().len_bytes().into()
10
+ }
11
+
12
+ pub fn cat_len_chars(&self) -> Self {
13
+ self.inner.clone().cat().len_chars().into()
14
+ }
15
+
16
+ pub fn cat_starts_with(&self, prefix: String) -> Self {
17
+ self.inner.clone().cat().starts_with(prefix).into()
18
+ }
19
+
20
+ pub fn cat_ends_with(&self, suffix: String) -> Self {
21
+ self.inner.clone().cat().ends_with(suffix).into()
22
+ }
23
+
24
+ pub fn cat_slice(&self, offset: i64, length: Option<usize>) -> Self {
25
+ self.inner.clone().cat().slice(offset, length).into()
26
+ }
7
27
  }
@@ -1,4 +1,8 @@
1
- use polars::prelude::DataTypeExpr;
1
+ use magnus::{IntoValue, Value};
2
+ use polars::prelude::{DataType, DataTypeExpr, Schema};
3
+
4
+ use crate::prelude::Wrap;
5
+ use crate::{RbExpr, RbPolarsErr, RbResult};
2
6
 
3
7
  #[magnus::wrap(class = "Polars::RbDataTypeExpr")]
4
8
  #[repr(transparent)]
@@ -12,3 +16,22 @@ impl From<DataTypeExpr> for RbDataTypeExpr {
12
16
  RbDataTypeExpr { inner: expr }
13
17
  }
14
18
  }
19
+
20
+ impl RbDataTypeExpr {
21
+ pub fn from_dtype(datatype: Wrap<DataType>) -> Self {
22
+ DataTypeExpr::Literal(datatype.0).into()
23
+ }
24
+
25
+ pub fn of_expr(expr: &RbExpr) -> Self {
26
+ DataTypeExpr::OfExpr(Box::new(expr.inner.clone())).into()
27
+ }
28
+
29
+ pub fn collect_dtype(&self, schema: Wrap<Schema>) -> RbResult<Value> {
30
+ let dtype = self
31
+ .clone()
32
+ .inner
33
+ .into_datatype(&schema.0)
34
+ .map_err(RbPolarsErr::from)?;
35
+ Ok(Wrap(dtype).into_value())
36
+ }
37
+ }
@@ -4,6 +4,20 @@ use crate::conversion::Wrap;
4
4
  use crate::{RbExpr, RbPolarsErr, RbResult};
5
5
 
6
6
  impl RbExpr {
7
+ pub fn dt_add_business_days(
8
+ &self,
9
+ n: &RbExpr,
10
+ week_mask: [bool; 7],
11
+ holidays: Vec<i32>,
12
+ roll: Wrap<Roll>,
13
+ ) -> Self {
14
+ self.inner
15
+ .clone()
16
+ .dt()
17
+ .add_business_days(n.inner.clone(), week_mask, holidays, roll.0)
18
+ .into()
19
+ }
20
+
7
21
  pub fn dt_to_string(&self, format: String) -> Self {
8
22
  self.inner.clone().dt().to_string(&format).into()
9
23
  }
@@ -90,6 +104,34 @@ impl RbExpr {
90
104
  self.inner.clone().dt().round(every.inner.clone()).into()
91
105
  }
92
106
 
107
+ #[allow(clippy::too_many_arguments)]
108
+ pub fn dt_replace(
109
+ &self,
110
+ year: &Self,
111
+ month: &Self,
112
+ day: &Self,
113
+ hour: &Self,
114
+ minute: &Self,
115
+ second: &Self,
116
+ microsecond: &Self,
117
+ ambiguous: &Self,
118
+ ) -> Self {
119
+ self.inner
120
+ .clone()
121
+ .dt()
122
+ .replace(
123
+ year.inner.clone(),
124
+ month.inner.clone(),
125
+ day.inner.clone(),
126
+ hour.inner.clone(),
127
+ minute.inner.clone(),
128
+ second.inner.clone(),
129
+ microsecond.inner.clone(),
130
+ ambiguous.inner.clone(),
131
+ )
132
+ .into()
133
+ }
134
+
93
135
  pub fn dt_combine(&self, time: &Self, time_unit: Wrap<TimeUnit>) -> Self {
94
136
  self.inner
95
137
  .clone()
@@ -98,10 +140,26 @@ impl RbExpr {
98
140
  .into()
99
141
  }
100
142
 
143
+ pub fn dt_millennium(&self) -> Self {
144
+ self.inner.clone().dt().millennium().into()
145
+ }
146
+
147
+ pub fn dt_century(&self) -> Self {
148
+ self.inner.clone().dt().century().into()
149
+ }
150
+
101
151
  pub fn dt_year(&self) -> Self {
102
152
  self.clone().inner.dt().year().into()
103
153
  }
104
154
 
155
+ pub fn dt_is_business_day(&self, week_mask: [bool; 7], holidays: Vec<i32>) -> Self {
156
+ self.inner
157
+ .clone()
158
+ .dt()
159
+ .is_business_day(week_mask, holidays)
160
+ .into()
161
+ }
162
+
105
163
  pub fn dt_is_leap_year(&self) -> Self {
106
164
  self.clone().inner.dt().is_leap_year().into()
107
165
  }