polars-df 0.4.0 → 0.5.0

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/Cargo.lock +272 -191
  4. data/Cargo.toml +0 -1
  5. data/README.md +2 -2
  6. data/ext/polars/Cargo.toml +8 -4
  7. data/ext/polars/src/apply/dataframe.rs +2 -2
  8. data/ext/polars/src/{lazy/apply.rs → apply/lazy.rs} +1 -2
  9. data/ext/polars/src/apply/mod.rs +1 -0
  10. data/ext/polars/src/batched_csv.rs +7 -5
  11. data/ext/polars/src/conversion.rs +106 -4
  12. data/ext/polars/src/dataframe.rs +19 -17
  13. data/ext/polars/src/error.rs +0 -4
  14. data/ext/polars/src/expr/binary.rs +69 -0
  15. data/ext/polars/src/expr/categorical.rs +10 -0
  16. data/ext/polars/src/expr/datetime.rs +223 -0
  17. data/ext/polars/src/expr/general.rs +933 -0
  18. data/ext/polars/src/expr/list.rs +146 -0
  19. data/ext/polars/src/{lazy → expr}/meta.rs +16 -6
  20. data/ext/polars/src/expr/string.rs +313 -0
  21. data/ext/polars/src/expr/struct.rs +15 -0
  22. data/ext/polars/src/expr.rs +33 -0
  23. data/ext/polars/src/functions/eager.rs +93 -0
  24. data/ext/polars/src/functions/io.rs +34 -0
  25. data/ext/polars/src/functions/lazy.rs +209 -0
  26. data/ext/polars/src/functions/meta.rs +8 -0
  27. data/ext/polars/src/functions/mod.rs +5 -0
  28. data/ext/polars/src/functions/whenthen.rs +43 -0
  29. data/ext/polars/src/{lazy/dataframe.rs → lazyframe.rs} +12 -33
  30. data/ext/polars/src/lazygroupby.rs +29 -0
  31. data/ext/polars/src/lib.rs +205 -303
  32. data/ext/polars/src/rb_modules.rs +8 -0
  33. data/ext/polars/src/series/aggregation.rs +83 -0
  34. data/ext/polars/src/series/arithmetic.rs +88 -0
  35. data/ext/polars/src/series/comparison.rs +251 -0
  36. data/ext/polars/src/series/construction.rs +164 -0
  37. data/ext/polars/src/series.rs +99 -539
  38. data/lib/polars/convert.rb +2 -2
  39. data/lib/polars/data_frame.rb +201 -50
  40. data/lib/polars/data_types.rb +6 -4
  41. data/lib/polars/date_time_expr.rb +142 -2
  42. data/lib/polars/expr.rb +70 -10
  43. data/lib/polars/lazy_frame.rb +4 -3
  44. data/lib/polars/lazy_functions.rb +4 -1
  45. data/lib/polars/list_expr.rb +68 -19
  46. data/lib/polars/series.rb +181 -73
  47. data/lib/polars/string_expr.rb +149 -43
  48. data/lib/polars/string_name_space.rb +4 -4
  49. data/lib/polars/struct_name_space.rb +32 -0
  50. data/lib/polars/utils.rb +41 -7
  51. data/lib/polars/version.rb +1 -1
  52. data/lib/polars.rb +2 -2
  53. metadata +26 -11
  54. data/ext/polars/src/lazy/dsl.rs +0 -1775
  55. data/ext/polars/src/lazy/mod.rs +0 -5
  56. data/ext/polars/src/lazy/utils.rs +0 -13
  57. data/ext/polars/src/list_construction.rs +0 -100
  58. /data/ext/polars/src/{numo.rs → series/export.rs} +0 -0
  59. /data/ext/polars/src/{set.rs → series/set_at_idx.rs} +0 -0
data/Cargo.toml CHANGED
@@ -3,7 +3,6 @@ members = ["ext/polars"]
3
3
 
4
4
  [patch.crates-io]
5
5
  jsonpath_lib = { git = "https://github.com/ritchie46/jsonpath", rev = "24eaf0b4416edff38a4d1b6b17bc4b9f3f047b4b" }
6
- halfbrown = { git = "https://github.com/Licenser/halfbrown", rev = "952023c5dd6461b009bb5ba66b9aa979bd75949f" }
7
6
 
8
7
  [profile.release]
9
8
  strip = true
data/README.md CHANGED
@@ -58,9 +58,9 @@ Polars.scan_parquet("file.parquet")
58
58
  From Active Record
59
59
 
60
60
  ```ruby
61
- Polars.read_sql(User.all)
61
+ Polars.read_database(User.all)
62
62
  # or
63
- Polars.read_sql("SELECT * FROM users")
63
+ Polars.read_database("SELECT * FROM users")
64
64
  ```
65
65
 
66
66
  From JSON
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "polars"
3
- version = "0.4.0"
3
+ version = "0.5.0"
4
4
  license = "MIT"
5
5
  authors = ["Andrew Kane <andrew@ankane.org>"]
6
6
  edition = "2021"
@@ -12,14 +12,15 @@ crate-type = ["cdylib"]
12
12
  [dependencies]
13
13
  ahash = "0.8"
14
14
  magnus = "0.5"
15
- polars-core = "0.28.0"
15
+ polars-core = "0.29.0"
16
16
  serde_json = "1"
17
17
  smartstring = "1"
18
18
 
19
19
  [dependencies.polars]
20
- version = "0.28.0"
20
+ version = "0.29.0"
21
21
  features = [
22
22
  "abs",
23
+ "approx_unique",
23
24
  "arange",
24
25
  "arg_where",
25
26
  "asof_join",
@@ -27,7 +28,7 @@ features = [
27
28
  "binary_encoding",
28
29
  "concat_str",
29
30
  "cse",
30
- "csv-file",
31
+ "csv",
31
32
  "cum_agg",
32
33
  "cumulative_eval",
33
34
  "dataframe_arithmetic",
@@ -49,7 +50,9 @@ features = [
49
50
  "json",
50
51
  "lazy",
51
52
  "lazy_regex",
53
+ "list_count",
52
54
  "list_eval",
55
+ "list_take",
53
56
  "list_to_struct",
54
57
  "log",
55
58
  "meta",
@@ -75,6 +78,7 @@ features = [
75
78
  "serde-lazy",
76
79
  "sign",
77
80
  "string_encoding",
81
+ "string_from_radix",
78
82
  "string_justify",
79
83
  "strings",
80
84
  "timezones",
@@ -202,8 +202,8 @@ pub fn apply_lambda_with_utf8_out_type(
202
202
  }
203
203
 
204
204
  /// Apply a lambda with list output type
205
- pub fn apply_lambda_with_list_out_type<'a>(
206
- df: &'a DataFrame,
205
+ pub fn apply_lambda_with_list_out_type(
206
+ df: &DataFrame,
207
207
  lambda: Value,
208
208
  init_null_count: usize,
209
209
  first_value: Option<&Series>,
@@ -1,8 +1,7 @@
1
1
  use magnus::Value;
2
2
  use polars::prelude::*;
3
3
 
4
- use crate::lazy::dsl::RbExpr;
5
- use crate::Wrap;
4
+ use crate::{RbExpr, Wrap};
6
5
 
7
6
  pub fn binary_lambda(_lambda: Value, _a: Series, _b: Series) -> PolarsResult<Option<Series>> {
8
7
  todo!();
@@ -1,4 +1,5 @@
1
1
  pub mod dataframe;
2
+ pub mod lazy;
2
3
  pub mod series;
3
4
 
4
5
  use magnus::{RHash, Value};
@@ -68,11 +68,13 @@ impl RbBatchedCsv {
68
68
  };
69
69
 
70
70
  let overwrite_dtype = overwrite_dtype.map(|overwrite_dtype| {
71
- let fields = overwrite_dtype.iter().map(|(name, dtype)| {
72
- let dtype = dtype.0.clone();
73
- Field::new(name, dtype)
74
- });
75
- Schema::from(fields)
71
+ overwrite_dtype
72
+ .iter()
73
+ .map(|(name, dtype)| {
74
+ let dtype = dtype.0.clone();
75
+ Field::new(name, dtype)
76
+ })
77
+ .collect::<Schema>()
76
78
  });
77
79
 
78
80
  let overwrite_dtype_slice = overwrite_dtype_slice.map(|overwrite_dtype| {
@@ -5,6 +5,7 @@ use magnus::{
5
5
  class, exception, r_hash::ForEach, ruby_handle::RubyHandle, Integer, IntoValue, Module, RArray,
6
6
  RFloat, RHash, RString, Symbol, TryConvert, Value, QNIL,
7
7
  };
8
+ use magnus::encoding::{EncodingCapable, Index};
8
9
  use polars::chunked_array::object::PolarsObjectSafe;
9
10
  use polars::chunked_array::ops::{FillNullLimit, FillNullStrategy};
10
11
  use polars::datatypes::AnyValue;
@@ -15,6 +16,7 @@ use polars::prelude::*;
15
16
  use polars::series::ops::NullBehavior;
16
17
  use smartstring::alias::String as SmartString;
17
18
 
19
+ use crate::rb_modules::utils;
18
20
  use crate::{RbDataFrame, RbLazyFrame, RbPolarsErr, RbResult, RbSeries, RbValueError};
19
21
 
20
22
  pub(crate) fn slice_to_wrapped<T>(slice: &[T]) -> &[Wrap<T>] {
@@ -23,6 +25,12 @@ pub(crate) fn slice_to_wrapped<T>(slice: &[T]) -> &[Wrap<T>] {
23
25
  unsafe { std::mem::transmute(slice) }
24
26
  }
25
27
 
28
+ pub(crate) fn slice_extract_wrapped<T>(slice: &[Wrap<T>]) -> &[T] {
29
+ // Safety:
30
+ // Wrap is transparent.
31
+ unsafe { std::mem::transmute(slice) }
32
+ }
33
+
26
34
  pub(crate) fn vec_extract_wrapped<T>(buf: Vec<Wrap<T>>) -> Vec<T> {
27
35
  // Safety:
28
36
  // Wrap is transparent.
@@ -180,7 +188,10 @@ impl IntoValue for Wrap<AnyValue<'_>> {
180
188
  t.funcall::<_, _, Value>("utc", ()).unwrap()
181
189
  }
182
190
  }
183
- AnyValue::Duration(_v, _tu) => todo!(),
191
+ AnyValue::Duration(v, tu) => {
192
+ let tu = tu.to_ascii();
193
+ utils().funcall("_to_ruby_duration", (v, tu)).unwrap()
194
+ }
184
195
  AnyValue::Time(_v) => todo!(),
185
196
  AnyValue::List(v) => RbSeries::new(v).to_a().into_value(),
186
197
  ref av @ AnyValue::Struct(_, _, flds) => struct_dict(av._iter_struct_av(), flds),
@@ -261,6 +272,75 @@ impl IntoValue for Wrap<DataType> {
261
272
  }
262
273
  }
263
274
 
275
+ impl IntoValue for Wrap<TimeUnit> {
276
+ fn into_value_with(self, _: &RubyHandle) -> Value {
277
+ let tu = match self.0 {
278
+ TimeUnit::Nanoseconds => "ns",
279
+ TimeUnit::Microseconds => "us",
280
+ TimeUnit::Milliseconds => "ms",
281
+ };
282
+ tu.into_value()
283
+ }
284
+ }
285
+
286
+ impl IntoValue for Wrap<&Utf8Chunked> {
287
+ fn into_value_with(self, _: &RubyHandle) -> Value {
288
+ let iter = self.0.into_iter();
289
+ RArray::from_iter(iter).into_value()
290
+ }
291
+ }
292
+
293
+ impl IntoValue for Wrap<&BinaryChunked> {
294
+ fn into_value_with(self, _: &RubyHandle) -> Value {
295
+ let iter = self
296
+ .0
297
+ .into_iter()
298
+ .map(|opt_bytes| opt_bytes.map(RString::from_slice));
299
+ RArray::from_iter(iter).into_value()
300
+ }
301
+ }
302
+
303
+ impl IntoValue for Wrap<&StructChunked> {
304
+ fn into_value_with(self, _: &RubyHandle) -> Value {
305
+ let s = self.0.clone().into_series();
306
+ // todo! iterate its chunks and flatten.
307
+ // make series::iter() accept a chunk index.
308
+ let s = s.rechunk();
309
+ let iter = s.iter().map(|av| {
310
+ if let AnyValue::Struct(_, _, flds) = av {
311
+ struct_dict(av._iter_struct_av(), flds)
312
+ } else {
313
+ unreachable!()
314
+ }
315
+ });
316
+
317
+ RArray::from_iter(iter).into_value()
318
+ }
319
+ }
320
+
321
+ impl IntoValue for Wrap<&DurationChunked> {
322
+ fn into_value_with(self, _: &RubyHandle) -> Value {
323
+ let utils = utils();
324
+ let tu = Wrap(self.0.time_unit()).into_value();
325
+ let iter = self.0.into_iter().map(|opt_v| {
326
+ opt_v.map(|v| {
327
+ utils
328
+ .funcall::<_, _, Value>("_to_ruby_duration", (v, tu))
329
+ .unwrap()
330
+ })
331
+ });
332
+ RArray::from_iter(iter).into_value()
333
+ }
334
+ }
335
+
336
+ impl TryConvert for Wrap<Field> {
337
+ fn try_convert(ob: Value) -> RbResult<Self> {
338
+ let name: String = ob.funcall("name", ())?;
339
+ let dtype: Wrap<DataType> = ob.funcall("dtype", ())?;
340
+ Ok(Wrap(Field::new(&name, dtype.0)))
341
+ }
342
+ }
343
+
264
344
  impl TryConvert for Wrap<DataType> {
265
345
  fn try_convert(ob: Value) -> RbResult<Self> {
266
346
  let dtype = if ob.is_kind_of(class::class()) {
@@ -294,6 +374,20 @@ impl TryConvert for Wrap<DataType> {
294
374
  )))
295
375
  }
296
376
  }
377
+ // TODO improve
378
+ } else if ob.try_convert::<String>().is_err() {
379
+ let name = unsafe { ob.class().name() }.into_owned();
380
+ match name.as_str() {
381
+ "Polars::Struct" => {
382
+ let arr: RArray = ob.funcall("fields", ())?;
383
+ let mut fields = Vec::with_capacity(arr.len());
384
+ for v in arr.each() {
385
+ fields.push(v?.try_convert::<Wrap<Field>>()?.0);
386
+ }
387
+ DataType::Struct(fields)
388
+ }
389
+ _ => todo!(),
390
+ }
297
391
  } else {
298
392
  match ob.try_convert::<String>()?.as_str() {
299
393
  "u8" => DataType::UInt8,
@@ -339,7 +433,11 @@ impl<'s> TryConvert for Wrap<AnyValue<'s>> {
339
433
  } else if let Some(v) = RFloat::from_value(ob) {
340
434
  Ok(AnyValue::Float64(v.to_f64()).into())
341
435
  } else if let Some(v) = RString::from_value(ob) {
342
- Ok(AnyValue::Utf8Owned(v.to_string()?.into()).into())
436
+ if v.enc_get() == Index::utf8() {
437
+ Ok(AnyValue::Utf8Owned(v.to_string()?.into()).into())
438
+ } else {
439
+ Ok(AnyValue::BinaryOwned(unsafe { v.as_slice() }.to_vec()).into())
440
+ }
343
441
  // call is_a? for ActiveSupport::TimeWithZone
344
442
  } else if ob.funcall::<_, _, bool>("is_a?", (class::time(),))? {
345
443
  let sec = ob.funcall::<_, _, i64>("to_i", ())?;
@@ -377,6 +475,10 @@ impl<'s> TryConvert for Wrap<AnyValue<'s>> {
377
475
  .map_err(RbPolarsErr::from)?;
378
476
  Ok(Wrap(AnyValue::List(s)))
379
477
  }
478
+ } else if ob.is_kind_of(crate::rb_modules::datetime()) {
479
+ let sec: i64 = ob.funcall("to_i", ())?;
480
+ let nsec: i64 = ob.funcall("nsec", ())?;
481
+ Ok(Wrap(AnyValue::Datetime(sec * 1_000_000_000 + nsec, TimeUnit::Nanoseconds, &None)))
380
482
  } else if ob.is_kind_of(crate::rb_modules::date()) {
381
483
  // convert to DateTime for UTC
382
484
  let v = ob
@@ -410,12 +512,12 @@ impl TryConvert for Wrap<Schema> {
410
512
 
411
513
  let mut schema = Vec::new();
412
514
  dict.foreach(|key: String, val: Wrap<DataType>| {
413
- schema.push(Field::new(&key, val.0));
515
+ schema.push(Ok(Field::new(&key, val.0)));
414
516
  Ok(ForEach::Continue)
415
517
  })
416
518
  .unwrap();
417
519
 
418
- Ok(Wrap(schema.into_iter().into()))
520
+ Ok(Wrap(schema.into_iter().collect::<RbResult<Schema>>()?))
419
521
  }
420
522
  }
421
523
 
@@ -48,20 +48,25 @@ impl RbDataFrame {
48
48
  crate::object::register_object_builder();
49
49
 
50
50
  let schema =
51
- rows_to_schema_supertypes(&rows, infer_schema_length).map_err(RbPolarsErr::from)?;
51
+ rows_to_schema_supertypes(&rows, infer_schema_length.map(|n| std::cmp::max(1, n)))
52
+ .map_err(RbPolarsErr::from)?;
52
53
  // replace inferred nulls with boolean
53
54
  let fields = schema.iter_fields().map(|mut fld| match fld.data_type() {
54
55
  DataType::Null => {
55
56
  fld.coerce(DataType::Boolean);
56
57
  fld
57
58
  }
59
+ DataType::Decimal(_, _) => {
60
+ fld.coerce(DataType::Decimal(None, None));
61
+ fld
62
+ }
58
63
  _ => fld,
59
64
  });
60
- let mut schema = Schema::from(fields);
65
+ let mut schema = Schema::from_iter(fields);
61
66
 
62
67
  if let Some(schema_overwrite) = schema_overwrite {
63
68
  for (i, (name, dtype)) in schema_overwrite.into_iter().enumerate() {
64
- if let Some((name_, dtype_)) = schema.get_index_mut(i) {
69
+ if let Some((name_, dtype_)) = schema.get_at_index_mut(i) {
65
70
  *name_ = name;
66
71
 
67
72
  // if user sets dtype unknown, we use the inferred datatype
@@ -139,11 +144,13 @@ impl RbDataFrame {
139
144
  };
140
145
 
141
146
  let overwrite_dtype = overwrite_dtype.map(|overwrite_dtype| {
142
- let fields = overwrite_dtype.iter().map(|(name, dtype)| {
143
- let dtype = dtype.0.clone();
144
- Field::new(name, dtype)
145
- });
146
- Schema::from(fields)
147
+ overwrite_dtype
148
+ .iter()
149
+ .map(|(name, dtype)| {
150
+ let dtype = dtype.0.clone();
151
+ Field::new(name, dtype)
152
+ })
153
+ .collect::<Schema>()
147
154
  });
148
155
 
149
156
  let overwrite_dtype_slice = overwrite_dtype_slice.map(|overwrite_dtype| {
@@ -512,12 +519,10 @@ impl RbDataFrame {
512
519
  }
513
520
  }
514
521
  }
515
- let st = st?;
522
+ let _st = st?;
516
523
 
517
- match st {
518
- // TODO
519
- _ => None,
520
- }
524
+ // TODO
525
+ None
521
526
  }
522
527
 
523
528
  pub fn write_parquet(
@@ -914,10 +919,7 @@ impl RbDataFrame {
914
919
  true => pivot_stable,
915
920
  false => pivot,
916
921
  };
917
- let agg_expr = match aggregate_expr {
918
- Some(aggregate_expr) => Some(aggregate_expr.inner.clone()),
919
- None => None,
920
- };
922
+ let agg_expr = aggregate_expr.map(|aggregate_expr| aggregate_expr.inner.clone());
921
923
  let df = fun(
922
924
  &self.df.borrow(),
923
925
  values,
@@ -22,10 +22,6 @@ impl RbPolarsErr {
22
22
  pub fn other(message: String) -> Error {
23
23
  Error::new(exception::runtime_error(), message)
24
24
  }
25
-
26
- pub fn todo() -> Error {
27
- Error::new(exception::runtime_error(), "not implemented yet")
28
- }
29
25
  }
30
26
 
31
27
  pub struct RbValueError {}
@@ -0,0 +1,69 @@
1
+ use polars::prelude::*;
2
+
3
+ use crate::RbExpr;
4
+
5
+ impl RbExpr {
6
+ pub fn bin_contains(&self, lit: Vec<u8>) -> Self {
7
+ self.inner.clone().binary().contains_literal(lit).into()
8
+ }
9
+
10
+ pub fn bin_ends_with(&self, sub: Vec<u8>) -> Self {
11
+ self.inner.clone().binary().ends_with(sub).into()
12
+ }
13
+
14
+ pub fn bin_starts_with(&self, sub: Vec<u8>) -> Self {
15
+ self.inner.clone().binary().starts_with(sub).into()
16
+ }
17
+
18
+ pub fn bin_hex_decode(&self, strict: bool) -> Self {
19
+ self.clone()
20
+ .inner
21
+ .map(
22
+ move |s| {
23
+ s.binary()?
24
+ .hex_decode(strict)
25
+ .map(|s| Some(s.into_series()))
26
+ },
27
+ GetOutput::same_type(),
28
+ )
29
+ .with_fmt("bin.hex_decode")
30
+ .into()
31
+ }
32
+
33
+ pub fn bin_base64_decode(&self, strict: bool) -> Self {
34
+ self.clone()
35
+ .inner
36
+ .map(
37
+ move |s| {
38
+ s.binary()?
39
+ .base64_decode(strict)
40
+ .map(|s| Some(s.into_series()))
41
+ },
42
+ GetOutput::same_type(),
43
+ )
44
+ .with_fmt("bin.base64_decode")
45
+ .into()
46
+ }
47
+
48
+ pub fn bin_hex_encode(&self) -> Self {
49
+ self.clone()
50
+ .inner
51
+ .map(
52
+ move |s| s.binary().map(|s| Some(s.hex_encode().into_series())),
53
+ GetOutput::same_type(),
54
+ )
55
+ .with_fmt("bin.hex_encode")
56
+ .into()
57
+ }
58
+
59
+ pub fn bin_base64_encode(&self) -> Self {
60
+ self.clone()
61
+ .inner
62
+ .map(
63
+ move |s| s.binary().map(|s| Some(s.base64_encode().into_series())),
64
+ GetOutput::same_type(),
65
+ )
66
+ .with_fmt("bin.base64_encode")
67
+ .into()
68
+ }
69
+ }
@@ -0,0 +1,10 @@
1
+ use polars::prelude::*;
2
+
3
+ use crate::conversion::Wrap;
4
+ use crate::RbExpr;
5
+
6
+ impl RbExpr {
7
+ pub fn cat_set_ordering(&self, ordering: Wrap<CategoricalOrdering>) -> Self {
8
+ self.inner.clone().cat().set_ordering(ordering.0).into()
9
+ }
10
+ }
@@ -0,0 +1,223 @@
1
+ use polars::prelude::*;
2
+
3
+ use crate::conversion::Wrap;
4
+ use crate::RbExpr;
5
+
6
+ impl RbExpr {
7
+ pub fn dt_to_string(&self, format: String) -> Self {
8
+ self.inner.clone().dt().to_string(&format).into()
9
+ }
10
+
11
+ pub fn dt_offset_by(&self, by: String) -> Self {
12
+ let by = Duration::parse(&by);
13
+ self.inner.clone().dt().offset_by(by).into()
14
+ }
15
+
16
+ pub fn dt_epoch_seconds(&self) -> Self {
17
+ self.clone()
18
+ .inner
19
+ .map(
20
+ |s| {
21
+ s.timestamp(TimeUnit::Milliseconds)
22
+ .map(|ca| Some((ca / 1000).into_series()))
23
+ },
24
+ GetOutput::from_type(DataType::Int64),
25
+ )
26
+ .into()
27
+ }
28
+
29
+ pub fn dt_with_time_unit(&self, tu: Wrap<TimeUnit>) -> Self {
30
+ self.inner.clone().dt().with_time_unit(tu.0).into()
31
+ }
32
+
33
+ pub fn dt_convert_time_zone(&self, tz: TimeZone) -> Self {
34
+ self.inner.clone().dt().convert_time_zone(tz).into()
35
+ }
36
+
37
+ pub fn dt_cast_time_unit(&self, tu: Wrap<TimeUnit>) -> Self {
38
+ self.inner.clone().dt().cast_time_unit(tu.0).into()
39
+ }
40
+
41
+ pub fn dt_replace_time_zone(&self, tz: Option<String>, use_earliest: Option<bool>) -> Self {
42
+ self.inner
43
+ .clone()
44
+ .dt()
45
+ .replace_time_zone(tz, use_earliest)
46
+ .into()
47
+ }
48
+
49
+ #[allow(deprecated)]
50
+ pub fn dt_tz_localize(&self, tz: String) -> Self {
51
+ self.inner.clone().dt().tz_localize(tz).into()
52
+ }
53
+
54
+ pub fn dt_truncate(&self, every: String, offset: String) -> Self {
55
+ self.inner.clone().dt().truncate(&every, &offset).into()
56
+ }
57
+
58
+ pub fn dt_month_start(&self) -> Self {
59
+ self.inner.clone().dt().month_start().into()
60
+ }
61
+
62
+ pub fn dt_month_end(&self) -> Self {
63
+ self.inner.clone().dt().month_end().into()
64
+ }
65
+
66
+ pub fn dt_round(&self, every: String, offset: String) -> Self {
67
+ self.inner.clone().dt().round(&every, &offset).into()
68
+ }
69
+
70
+ pub fn dt_combine(&self, time: &Self, time_unit: Wrap<TimeUnit>) -> Self {
71
+ self.inner
72
+ .clone()
73
+ .dt()
74
+ .combine(time.inner.clone(), time_unit.0)
75
+ .into()
76
+ }
77
+
78
+ pub fn dt_year(&self) -> Self {
79
+ self.clone().inner.dt().year().into()
80
+ }
81
+
82
+ pub fn dt_is_leap_year(&self) -> Self {
83
+ self.clone().inner.dt().is_leap_year().into()
84
+ }
85
+
86
+ pub fn dt_iso_year(&self) -> Self {
87
+ self.clone().inner.dt().iso_year().into()
88
+ }
89
+
90
+ pub fn dt_quarter(&self) -> Self {
91
+ self.clone().inner.dt().quarter().into()
92
+ }
93
+
94
+ pub fn dt_month(&self) -> Self {
95
+ self.clone().inner.dt().month().into()
96
+ }
97
+
98
+ pub fn dt_week(&self) -> Self {
99
+ self.clone().inner.dt().week().into()
100
+ }
101
+
102
+ pub fn dt_weekday(&self) -> Self {
103
+ self.clone().inner.dt().weekday().into()
104
+ }
105
+
106
+ pub fn dt_day(&self) -> Self {
107
+ self.clone().inner.dt().day().into()
108
+ }
109
+
110
+ pub fn dt_ordinal_day(&self) -> Self {
111
+ self.clone().inner.dt().ordinal_day().into()
112
+ }
113
+
114
+ pub fn dt_time(&self) -> Self {
115
+ self.clone().inner.dt().time().into()
116
+ }
117
+
118
+ pub fn dt_date(&self) -> Self {
119
+ self.clone().inner.dt().date().into()
120
+ }
121
+
122
+ pub fn dt_datetime(&self) -> Self {
123
+ self.clone().inner.dt().datetime().into()
124
+ }
125
+
126
+ pub fn dt_hour(&self) -> Self {
127
+ self.clone().inner.dt().hour().into()
128
+ }
129
+
130
+ pub fn dt_minute(&self) -> Self {
131
+ self.clone().inner.dt().minute().into()
132
+ }
133
+
134
+ pub fn dt_second(&self) -> Self {
135
+ self.clone().inner.dt().second().into()
136
+ }
137
+
138
+ pub fn dt_millisecond(&self) -> Self {
139
+ self.clone().inner.dt().millisecond().into()
140
+ }
141
+
142
+ pub fn dt_microsecond(&self) -> Self {
143
+ self.clone().inner.dt().microsecond().into()
144
+ }
145
+
146
+ pub fn dt_nanosecond(&self) -> Self {
147
+ self.clone().inner.dt().nanosecond().into()
148
+ }
149
+
150
+ pub fn dt_timestamp(&self, tu: Wrap<TimeUnit>) -> Self {
151
+ self.inner.clone().dt().timestamp(tu.0).into()
152
+ }
153
+
154
+ pub fn duration_days(&self) -> Self {
155
+ self.inner
156
+ .clone()
157
+ .map(
158
+ |s| Ok(Some(s.duration()?.days().into_series())),
159
+ GetOutput::from_type(DataType::Int64),
160
+ )
161
+ .into()
162
+ }
163
+
164
+ pub fn duration_hours(&self) -> Self {
165
+ self.inner
166
+ .clone()
167
+ .map(
168
+ |s| Ok(Some(s.duration()?.hours().into_series())),
169
+ GetOutput::from_type(DataType::Int64),
170
+ )
171
+ .into()
172
+ }
173
+
174
+ pub fn duration_minutes(&self) -> Self {
175
+ self.inner
176
+ .clone()
177
+ .map(
178
+ |s| Ok(Some(s.duration()?.minutes().into_series())),
179
+ GetOutput::from_type(DataType::Int64),
180
+ )
181
+ .into()
182
+ }
183
+
184
+ pub fn duration_seconds(&self) -> Self {
185
+ self.inner
186
+ .clone()
187
+ .map(
188
+ |s| Ok(Some(s.duration()?.seconds().into_series())),
189
+ GetOutput::from_type(DataType::Int64),
190
+ )
191
+ .into()
192
+ }
193
+
194
+ pub fn duration_milliseconds(&self) -> Self {
195
+ self.inner
196
+ .clone()
197
+ .map(
198
+ |s| Ok(Some(s.duration()?.milliseconds().into_series())),
199
+ GetOutput::from_type(DataType::Int64),
200
+ )
201
+ .into()
202
+ }
203
+
204
+ pub fn duration_microseconds(&self) -> Self {
205
+ self.inner
206
+ .clone()
207
+ .map(
208
+ |s| Ok(Some(s.duration()?.microseconds().into_series())),
209
+ GetOutput::from_type(DataType::Int64),
210
+ )
211
+ .into()
212
+ }
213
+
214
+ pub fn duration_nanoseconds(&self) -> Self {
215
+ self.inner
216
+ .clone()
217
+ .map(
218
+ |s| Ok(Some(s.duration()?.nanoseconds().into_series())),
219
+ GetOutput::from_type(DataType::Int64),
220
+ )
221
+ .into()
222
+ }
223
+ }