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
@@ -0,0 +1,52 @@
1
+ module Polars
2
+ # A lazily instantiated `DataType` that can be used in an `Expr`.
3
+ class DataTypeExpr
4
+ # @private
5
+ attr_accessor :_rbdatatype_expr
6
+
7
+ # @private
8
+ def self._from_rbdatatype_expr(rbdatatype_expr)
9
+ slf = new
10
+ slf._rbdatatype_expr = rbdatatype_expr
11
+ slf
12
+ end
13
+
14
+ # Materialize the `DataTypeExpr` in a specific context.
15
+ #
16
+ # This is a useful function when debugging datatype expressions.
17
+ #
18
+ # @return [DataType]
19
+ #
20
+ # @example
21
+ # lf = Polars::LazyFrame.new(
22
+ # {
23
+ # "a" => [1, 2, 3]
24
+ # }
25
+ # )
26
+ # Polars.dtype_of("a").collect_dtype(lf)
27
+ # # => Polars::Int64
28
+ #
29
+ # @example
30
+ # Polars.dtype_of("a").collect_dtype({"a" => Polars::String})
31
+ # # => Polars::String
32
+ def collect_dtype(
33
+ context
34
+ )
35
+ schema = nil
36
+ if context.is_a?(Schema)
37
+ schema = context
38
+ elsif context.is_a?(Hash)
39
+ schema = Schema.new(context)
40
+ elsif context.is_a?(DataFrame)
41
+ schema = context.schema
42
+ elsif context.is_a?(LazyFrame)
43
+ schema = context.collect_schema
44
+ else
45
+ msg = "DataTypeExpr.collect_dtype did not expect #{context.inspect}"
46
+ raise TypeError, msg
47
+ end
48
+
49
+ _rbdatatype_expr.collect_dtype(schema.to_h)
50
+ end
51
+ end
52
+ end
@@ -99,7 +99,18 @@ module Polars
99
99
  self < NestedType
100
100
  end
101
101
 
102
- [:numeric?, :decimal?, :integer?, :signed_integer?, :unsigned_integer?, :float?, :temporal?, :nested?].each do |v|
102
+ # Return a `DataTypeExpr` with a static `DataType`.
103
+ #
104
+ # @return [Expr]
105
+ #
106
+ # @example
107
+ # Polars::Int16.new.to_dtype_expr.collect_dtype({})
108
+ # # => Polars::Int16
109
+ def self.to_dtype_expr
110
+ DataTypeExpr._from_rbdatatype_expr(RbDataTypeExpr.from_dtype(self))
111
+ end
112
+
113
+ [:numeric?, :decimal?, :integer?, :signed_integer?, :unsigned_integer?, :float?, :temporal?, :nested?, :to_dtype_expr].each do |v|
103
114
  define_method(v) do
104
115
  self.class.public_send(v)
105
116
  end
@@ -317,6 +328,7 @@ module Polars
317
328
  raise Todo
318
329
  end
319
330
 
331
+ # @private
320
332
  def self._from_rb_categories(rb_categories)
321
333
  slf = new
322
334
  slf._categories = rb_categories
@@ -401,7 +413,7 @@ module Polars
401
413
  class Object < DataType
402
414
  end
403
415
 
404
- # Type representing Null / None values.
416
+ # Type representing Null / nil values.
405
417
  class Null < DataType
406
418
  end
407
419
 
@@ -9,6 +9,57 @@ module Polars
9
9
  self._rbexpr = expr._rbexpr
10
10
  end
11
11
 
12
+ # Offset by `n` business days.
13
+ #
14
+ # @note
15
+ # This functionality is considered **unstable**. It may be changed
16
+ # at any point without it being considered a breaking change.
17
+ #
18
+ # @param n
19
+ # Number of business days to offset by. Can be a single number of an
20
+ # expression.
21
+ # @param week_mask
22
+ # Which days of the week to count. The default is Monday to Friday.
23
+ # If you wanted to count only Monday to Thursday, you would pass
24
+ # `[true, true, true, true, false, false, false]`.
25
+ # @param roll
26
+ # What to do when the start date lands on a non-business day. Options are:
27
+ #
28
+ # - `'raise'`: raise an error
29
+ # - `'forward'`: move to the next business day
30
+ # - `'backward'`: move to the previous business day
31
+ #
32
+ # @return [Expr]
33
+ #
34
+ # @example
35
+ # df = Polars::DataFrame.new({"start" => [Date.new(2020, 1, 1), Date.new(2020, 1, 2)]})
36
+ # df.with_columns(result: Polars.col("start").dt.add_business_days(5))
37
+ # # =>
38
+ # # shape: (2, 2)
39
+ # # ┌────────────┬────────────┐
40
+ # # │ start ┆ result │
41
+ # # │ --- ┆ --- │
42
+ # # │ date ┆ date │
43
+ # # ╞════════════╪════════════╡
44
+ # # │ 2020-01-01 ┆ 2020-01-08 │
45
+ # # │ 2020-01-02 ┆ 2020-01-09 │
46
+ # # └────────────┴────────────┘
47
+ def add_business_days(
48
+ n,
49
+ week_mask: [true, true, true, true, true, false, false],
50
+ roll: "raise"
51
+ )
52
+ n_rbexpr = Utils.parse_into_expression(n)
53
+ Utils.wrap_expr(
54
+ _rbexpr.dt_add_business_days(
55
+ n_rbexpr,
56
+ week_mask,
57
+ [],
58
+ roll
59
+ )
60
+ )
61
+ end
62
+
12
63
  # Divide the date/datetime range into buckets.
13
64
  #
14
65
  # Each date/datetime is mapped to the start of its bucket.
@@ -203,6 +254,93 @@ module Polars
203
254
  Utils.wrap_expr(_rbexpr.dt_round(every))
204
255
  end
205
256
 
257
+ # Replace time unit.
258
+ #
259
+ # @param year [Object]
260
+ # Column or literal.
261
+ # @param month [Object]
262
+ # Column or literal, ranging from 1-12.
263
+ # @param day [Object]
264
+ # Column or literal, ranging from 1-31.
265
+ # @param hour [Object]
266
+ # Column or literal, ranging from 0-23.
267
+ # @param minute [Object]
268
+ # Column or literal, ranging from 0-59.
269
+ # @param second [Object]
270
+ # Column or literal, ranging from 0-59.
271
+ # @param microsecond [Object]
272
+ # Column or literal, ranging from 0-999999.
273
+ # @param ambiguous [String]
274
+ # Determine how to deal with ambiguous datetimes:
275
+ #
276
+ # - `'raise'` (default): raise
277
+ # - `'earliest'`: use the earliest datetime
278
+ # - `'latest'`: use the latest datetime
279
+ # - `'null'`: set to null
280
+ #
281
+ # @return [Expr]
282
+ #
283
+ # @example
284
+ # df = Polars::DataFrame.new(
285
+ # {
286
+ # "date" => [Date.new(2024, 4, 1), Date.new(2025, 3, 16)],
287
+ # "new_day" => [10, 15]
288
+ # }
289
+ # )
290
+ # df.with_columns(Polars.col("date").dt.replace(day: "new_day").alias("replaced"))
291
+ # # =>
292
+ # # shape: (2, 3)
293
+ # # ┌────────────┬─────────┬────────────┐
294
+ # # │ date ┆ new_day ┆ replaced │
295
+ # # │ --- ┆ --- ┆ --- │
296
+ # # │ date ┆ i64 ┆ date │
297
+ # # ╞════════════╪═════════╪════════════╡
298
+ # # │ 2024-04-01 ┆ 10 ┆ 2024-04-10 │
299
+ # # │ 2025-03-16 ┆ 15 ┆ 2025-03-15 │
300
+ # # └────────────┴─────────┴────────────┘
301
+ #
302
+ # @example
303
+ # df.with_columns(Polars.col("date").dt.replace(year: 1800).alias("replaced"))
304
+ # # =>
305
+ # # shape: (2, 3)
306
+ # # ┌────────────┬─────────┬────────────┐
307
+ # # │ date ┆ new_day ┆ replaced │
308
+ # # │ --- ┆ --- ┆ --- │
309
+ # # │ date ┆ i64 ┆ date │
310
+ # # ╞════════════╪═════════╪════════════╡
311
+ # # │ 2024-04-01 ┆ 10 ┆ 1800-04-01 │
312
+ # # │ 2025-03-16 ┆ 15 ┆ 1800-03-16 │
313
+ # # └────────────┴─────────┴────────────┘
314
+ def replace(
315
+ year: nil,
316
+ month: nil,
317
+ day: nil,
318
+ hour: nil,
319
+ minute: nil,
320
+ second: nil,
321
+ microsecond: nil,
322
+ ambiguous: "raise"
323
+ )
324
+ day, month, year, hour, minute, second, microsecond = (
325
+ Utils.parse_into_list_of_expressions(
326
+ day, month, year, hour, minute, second, microsecond
327
+ )
328
+ )
329
+ ambiguous_expr = Utils.parse_into_expression(ambiguous, str_as_lit: true)
330
+ Utils.wrap_expr(
331
+ _rbexpr.dt_replace(
332
+ year,
333
+ month,
334
+ day,
335
+ hour,
336
+ minute,
337
+ second,
338
+ microsecond,
339
+ ambiguous_expr
340
+ )
341
+ )
342
+ end
343
+
206
344
  # Create a naive Datetime from an existing Date/Datetime expression and a Time.
207
345
  #
208
346
  # If the underlying expression is a Datetime then its time component is replaced,
@@ -317,6 +455,82 @@ module Polars
317
455
  Utils.wrap_expr(_rbexpr.strftime(fmt))
318
456
  end
319
457
 
458
+ # Extract the millennium from underlying representation.
459
+ #
460
+ # Applies to Date and Datetime columns.
461
+ #
462
+ # Returns the millennium number in the calendar date.
463
+ #
464
+ # @return [Expr]
465
+ #
466
+ # @example
467
+ # df = Polars::DataFrame.new(
468
+ # {
469
+ # "date" => [
470
+ # Date.new(999, 12, 31),
471
+ # Date.new(1897, 5, 7),
472
+ # Date.new(2000, 1, 1),
473
+ # Date.new(2001, 7, 5),
474
+ # Date.new(3002, 10, 20)
475
+ # ]
476
+ # }
477
+ # )
478
+ # df.with_columns(mlnm: Polars.col("date").dt.millennium)
479
+ # # =>
480
+ # # shape: (5, 2)
481
+ # # ┌────────────┬──────┐
482
+ # # │ date ┆ mlnm │
483
+ # # │ --- ┆ --- │
484
+ # # │ date ┆ i32 │
485
+ # # ╞════════════╪══════╡
486
+ # # │ 0999-12-31 ┆ 1 │
487
+ # # │ 1897-05-07 ┆ 2 │
488
+ # # │ 2000-01-01 ┆ 2 │
489
+ # # │ 2001-07-05 ┆ 3 │
490
+ # # │ 3002-10-20 ┆ 4 │
491
+ # # └────────────┴──────┘
492
+ def millennium
493
+ Utils.wrap_expr(_rbexpr.dt_millennium)
494
+ end
495
+
496
+ # Extract the century from underlying representation.
497
+ #
498
+ # Applies to Date and Datetime columns.
499
+ #
500
+ # Returns the century number in the calendar date.
501
+ #
502
+ # @return [Expr]
503
+ #
504
+ # @example
505
+ # df = Polars::DataFrame.new(
506
+ # {
507
+ # "date" => [
508
+ # Date.new(999, 12, 31),
509
+ # Date.new(1897, 5, 7),
510
+ # Date.new(2000, 1, 1),
511
+ # Date.new(2001, 7, 5),
512
+ # Date.new(3002, 10, 20)
513
+ # ]
514
+ # }
515
+ # )
516
+ # df.with_columns(cent: Polars.col("date").dt.century)
517
+ # # =>
518
+ # # shape: (5, 2)
519
+ # # ┌────────────┬──────┐
520
+ # # │ date ┆ cent │
521
+ # # │ --- ┆ --- │
522
+ # # │ date ┆ i32 │
523
+ # # ╞════════════╪══════╡
524
+ # # │ 0999-12-31 ┆ 10 │
525
+ # # │ 1897-05-07 ┆ 19 │
526
+ # # │ 2000-01-01 ┆ 20 │
527
+ # # │ 2001-07-05 ┆ 21 │
528
+ # # │ 3002-10-20 ┆ 31 │
529
+ # # └────────────┴──────┘
530
+ def century
531
+ Utils.wrap_expr(_rbexpr.dt_century)
532
+ end
533
+
320
534
  # Extract year from underlying Date representation.
321
535
  #
322
536
  # Applies to Date and Datetime columns.
@@ -348,6 +562,43 @@ module Polars
348
562
  Utils.wrap_expr(_rbexpr.dt_year)
349
563
  end
350
564
 
565
+ # Determine whether each day lands on a business day.
566
+ #
567
+ # @note
568
+ # This functionality is considered **unstable**. It may be changed
569
+ # at any point without it being considered a breaking change.
570
+ #
571
+ # @param week_mask [Array]
572
+ # Which days of the week to count. The default is Monday to Friday.
573
+ # If you wanted to count only Monday to Thursday, you would pass
574
+ # `[true, true, true, true, false, false, false]`.
575
+ #
576
+ # @return [Expr]
577
+ #
578
+ # @example
579
+ # df = Polars::DataFrame.new({"start" => [Date.new(2020, 1, 3), Date.new(2020, 1, 5)]})
580
+ # df.with_columns(is_business_day: Polars.col("start").dt.is_business_day)
581
+ # # =>
582
+ # # shape: (2, 2)
583
+ # # ┌────────────┬─────────────────┐
584
+ # # │ start ┆ is_business_day │
585
+ # # │ --- ┆ --- │
586
+ # # │ date ┆ bool │
587
+ # # ╞════════════╪═════════════════╡
588
+ # # │ 2020-01-03 ┆ true │
589
+ # # │ 2020-01-05 ┆ false │
590
+ # # └────────────┴─────────────────┘
591
+ def is_business_day(
592
+ week_mask: [true, true, true, true, true, false, false]
593
+ )
594
+ Utils.wrap_expr(
595
+ _rbexpr.dt_is_business_day(
596
+ week_mask,
597
+ []
598
+ )
599
+ )
600
+ end
601
+
351
602
  # Determine whether the year of the underlying date is a leap year.
352
603
  #
353
604
  # Applies to Date and Datetime columns.
@@ -18,6 +18,68 @@ module Polars
18
18
  s[item]
19
19
  end
20
20
 
21
+ # Offset by `n` business days.
22
+ #
23
+ # @note
24
+ # This functionality is considered **unstable**. It may be changed
25
+ # at any point without it being considered a breaking change.
26
+ #
27
+ # @param n [Object]
28
+ # Number of business days to offset by. Can be a single number of an
29
+ # expression.
30
+ # @param week_mask [Array]
31
+ # Which days of the week to count. The default is Monday to Friday.
32
+ # If you wanted to count only Monday to Thursday, you would pass
33
+ # `[true, true, true, true, false, false, false]`.
34
+ # roll
35
+ # What to do when the start date lands on a non-business day. Options are:
36
+ #
37
+ # - `'raise'`: raise an error
38
+ # - `'forward'`: move to the next business day
39
+ # - `'backward'`: move to the previous business day
40
+ #
41
+ # @return [Series]
42
+ #
43
+ # @example
44
+ # s = Polars::Series.new("start", [Date.new(2020, 1, 1), Date.new(2020, 1, 2)])
45
+ # s.dt.add_business_days(5)
46
+ # # =>
47
+ # # shape: (2,)
48
+ # # Series: 'start' [date]
49
+ # # [
50
+ # # 2020-01-08
51
+ # # 2020-01-09
52
+ # # ]
53
+ #
54
+ # @example You can pass a custom weekend - for example, if you only take Sunday off:
55
+ # week_mask = [true, true, true, true, true, true, false]
56
+ # s.dt.add_business_days(5, week_mask: week_mask)
57
+ # # =>
58
+ # # shape: (2,)
59
+ # # Series: 'start' [date]
60
+ # # [
61
+ # # 2020-01-07
62
+ # # 2020-01-08
63
+ # # ]
64
+ #
65
+ # @example Roll all dates forwards to the next business day:
66
+ # s = Polars::Series.new("start", [Date.new(2020, 1, 5), Date.new(2020, 1, 6)])
67
+ # s.dt.add_business_days(0, roll: "forward")
68
+ # # =>
69
+ # # shape: (2,)
70
+ # # Series: 'start' [date]
71
+ # # [
72
+ # # 2020-01-06
73
+ # # 2020-01-06
74
+ # # ]
75
+ def add_business_days(
76
+ n,
77
+ week_mask: [true, true, true, true, true, false, false],
78
+ roll: "raise"
79
+ )
80
+ super
81
+ end
82
+
21
83
  # Return minimum as Ruby object.
22
84
  #
23
85
  # @return [Object]
@@ -139,6 +201,74 @@ module Polars
139
201
  super
140
202
  end
141
203
 
204
+ # Extract the millennium from underlying representation.
205
+ #
206
+ # Applies to Date and Datetime columns.
207
+ #
208
+ # Returns the millennium number in the calendar date.
209
+ #
210
+ # @return [Series]
211
+ #
212
+ # @example
213
+ # s = Polars::Series.new(
214
+ # "dt",
215
+ # [
216
+ # Date.new(999, 12, 31),
217
+ # Date.new(1897, 5, 7),
218
+ # Date.new(2000, 1, 1),
219
+ # Date.new(2001, 7, 5),
220
+ # Date.new(3002, 10, 20)
221
+ # ]
222
+ # )
223
+ # s.dt.millennium
224
+ # # =>
225
+ # # shape: (5,)
226
+ # # Series: 'dt' [i32]
227
+ # # [
228
+ # # 1
229
+ # # 2
230
+ # # 2
231
+ # # 3
232
+ # # 4
233
+ # # ]
234
+ def millennium
235
+ super
236
+ end
237
+
238
+ # Extract the century from underlying representation.
239
+ #
240
+ # Applies to Date and Datetime columns.
241
+ #
242
+ # Returns the century number in the calendar date.
243
+ #
244
+ # @return [Series]
245
+ #
246
+ # @example
247
+ # s = Polars::Series.new(
248
+ # "dt",
249
+ # [
250
+ # Date.new(999, 12, 31),
251
+ # Date.new(1897, 5, 7),
252
+ # Date.new(2000, 1, 1),
253
+ # Date.new(2001, 7, 5),
254
+ # Date.new(3002, 10, 20)
255
+ # ]
256
+ # )
257
+ # s.dt.century
258
+ # # =>
259
+ # # shape: (5,)
260
+ # # Series: 'dt' [i32]
261
+ # # [
262
+ # # 10
263
+ # # 19
264
+ # # 20
265
+ # # 21
266
+ # # 31
267
+ # # ]
268
+ def century
269
+ super
270
+ end
271
+
142
272
  # Extract the year from the underlying date representation.
143
273
  #
144
274
  # Applies to Date and Datetime columns.
@@ -161,6 +291,69 @@ module Polars
161
291
  super
162
292
  end
163
293
 
294
+ # Determine whether each day lands on a business day.
295
+ #
296
+ # @note
297
+ # This functionality is considered **unstable**. It may be changed
298
+ # at any point without it being considered a breaking change.
299
+ #
300
+ # @param week_mask [Array]
301
+ # Which days of the week to count. The default is Monday to Friday.
302
+ # If you wanted to count only Monday to Thursday, you would pass
303
+ # `(True, True, True, True, False, False, False)`.
304
+ #
305
+ # @return [Series]
306
+ #
307
+ # @example
308
+ # s = Polars::Series.new([Date.new(2020, 1, 3), Date.new(2020, 1, 5)])
309
+ # s.dt.is_business_day
310
+ # # =>
311
+ # # shape: (2,)
312
+ # # Series: '' [bool]
313
+ # # [
314
+ # # true
315
+ # # false
316
+ # # ]
317
+ #
318
+ # @example You can pass a custom weekend - for example, if you only take Sunday off:
319
+ # week_mask = [true, true, true, true, true, true, false]
320
+ # s.dt.is_business_day(week_mask: week_mask)
321
+ # # =>
322
+ # # shape: (2,)
323
+ # # Series: '' [bool]
324
+ # # [
325
+ # # true
326
+ # # false
327
+ # # ]
328
+ def is_business_day(
329
+ week_mask: [true, true, true, true, true, false, false]
330
+ )
331
+ super
332
+ end
333
+
334
+ # Determine whether the year of the underlying date representation is a leap year.
335
+ #
336
+ # Applies to Date and Datetime columns.
337
+ #
338
+ # @return [Series]
339
+ #
340
+ # @example
341
+ # s = Polars::Series.new(
342
+ # "date", [Date.new(2000, 1, 1), Date.new(2001, 1, 1), Date.new(2002, 1, 1)]
343
+ # )
344
+ # s.dt.is_leap_year
345
+ # # =>
346
+ # # shape: (3,)
347
+ # # Series: 'date' [bool]
348
+ # # [
349
+ # # true
350
+ # # false
351
+ # # false
352
+ # # ]
353
+ def is_leap_year
354
+ super
355
+ end
356
+
164
357
  # Extract ISO year from underlying Date representation.
165
358
  #
166
359
  # Applies to Date and Datetime columns.
@@ -346,6 +539,48 @@ module Polars
346
539
  super
347
540
  end
348
541
 
542
+ # Extract (local) time.
543
+ #
544
+ # Applies to Date/Datetime/Time columns.
545
+ #
546
+ # @return
547
+ #
548
+ # @example
549
+ # ser = Polars::Series.new([DateTime.new(2021, 1, 2, 5)]).dt.replace_time_zone(
550
+ # "Asia/Kathmandu"
551
+ # )
552
+ # ser.dt.time
553
+ # # =>
554
+ # # shape: (1,)
555
+ # # Series: '' [time]
556
+ # # [
557
+ # # 05:00:00
558
+ # # ]
559
+ def time
560
+ super
561
+ end
562
+
563
+ # Extract (local) date.
564
+ #
565
+ # Applies to Date/Datetime columns.
566
+ #
567
+ # @return [Series]
568
+ #
569
+ # @example
570
+ # ser = Polars::Series.new([DateTime.new(2021, 1, 2, 5)]).dt.replace_time_zone(
571
+ # "Asia/Kathmandu"
572
+ # )
573
+ # ser.dt.date
574
+ # # =>
575
+ # # shape: (1,)
576
+ # # Series: '' [date]
577
+ # # [
578
+ # # 2021-01-02
579
+ # # ]
580
+ def date
581
+ super
582
+ end
583
+
349
584
  # Extract the hour from the underlying DateTime representation.
350
585
  #
351
586
  # Applies to Datetime columns.
@@ -1276,6 +1511,21 @@ module Polars
1276
1511
  super
1277
1512
  end
1278
1513
 
1514
+ # Create a naive Datetime from an existing Date/Datetime expression and a Time.
1515
+ #
1516
+ # If the underlying expression is a Datetime then its time component is replaced,
1517
+ # and if it is a Date then a new Datetime is created by combining the two values.
1518
+ #
1519
+ # @param time [Object]
1520
+ # A Ruby time literal or Series of the same length as this Series.
1521
+ # @param time_unit ['ns', 'us', 'ms']
1522
+ # Unit of time.
1523
+ #
1524
+ # @return [Series]
1525
+ def combine(time, time_unit: "us")
1526
+ super
1527
+ end
1528
+
1279
1529
  # Roll backward to the first day of the month.
1280
1530
  #
1281
1531
  # @return [Series]
@@ -1370,5 +1620,54 @@ module Polars
1370
1620
  def dst_offset
1371
1621
  super
1372
1622
  end
1623
+
1624
+ # Replace time unit.
1625
+ #
1626
+ # @param year [Object]
1627
+ # Literal or Series.
1628
+ # @param month [Object]
1629
+ # Literal or Series, ranging from 1-12.
1630
+ # @param day [Object]
1631
+ # Literal or Series, ranging from 1-31.
1632
+ # @param hour [Object]
1633
+ # Literal or Series, ranging from 0-23.
1634
+ # @param minute [Object]
1635
+ # Literal or Series, ranging from 0-59.
1636
+ # @param second [Object]
1637
+ # Literal or Series, ranging from 0-59.
1638
+ # @param microsecond [Object]
1639
+ # Literal or Series, ranging from 0-999999.
1640
+ # @param ambiguous [String]
1641
+ # Determine how to deal with ambiguous datetimes:
1642
+ #
1643
+ # - `'raise'` (default): raise
1644
+ # - `'earliest'`: use the earliest datetime
1645
+ # - `'latest'`: use the latest datetime
1646
+ # - `'null'`: set to null
1647
+ #
1648
+ # @return [Series]
1649
+ #
1650
+ # @example
1651
+ # s = Polars::Series.new("date", [Date.new(2013, 1, 1), Date.new(2024, 1, 2)])
1652
+ # s.dt.replace(year: 1800)
1653
+ # # =>
1654
+ # # shape: (2,)
1655
+ # # Series: 'date' [date]
1656
+ # # [
1657
+ # # 1800-01-01
1658
+ # # 1800-01-02
1659
+ # # ]
1660
+ def replace(
1661
+ year: nil,
1662
+ month: nil,
1663
+ day: nil,
1664
+ hour: nil,
1665
+ minute: nil,
1666
+ second: nil,
1667
+ microsecond: nil,
1668
+ ambiguous: "raise"
1669
+ )
1670
+ super
1671
+ end
1373
1672
  end
1374
1673
  end