polars-df 0.10.0-x86_64-linux-musl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +3 -0
  3. data/CHANGELOG.md +175 -0
  4. data/Cargo.lock +2536 -0
  5. data/Cargo.toml +6 -0
  6. data/LICENSE-THIRD-PARTY.txt +38726 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.md +437 -0
  9. data/lib/polars/3.1/polars.so +0 -0
  10. data/lib/polars/3.2/polars.so +0 -0
  11. data/lib/polars/3.3/polars.so +0 -0
  12. data/lib/polars/array_expr.rb +537 -0
  13. data/lib/polars/array_name_space.rb +423 -0
  14. data/lib/polars/batched_csv_reader.rb +98 -0
  15. data/lib/polars/binary_expr.rb +77 -0
  16. data/lib/polars/binary_name_space.rb +66 -0
  17. data/lib/polars/cat_expr.rb +72 -0
  18. data/lib/polars/cat_name_space.rb +125 -0
  19. data/lib/polars/config.rb +530 -0
  20. data/lib/polars/convert.rb +93 -0
  21. data/lib/polars/data_frame.rb +5418 -0
  22. data/lib/polars/data_types.rb +466 -0
  23. data/lib/polars/date_time_expr.rb +1444 -0
  24. data/lib/polars/date_time_name_space.rb +1484 -0
  25. data/lib/polars/dynamic_group_by.rb +52 -0
  26. data/lib/polars/exceptions.rb +31 -0
  27. data/lib/polars/expr.rb +6105 -0
  28. data/lib/polars/expr_dispatch.rb +22 -0
  29. data/lib/polars/functions/aggregation/horizontal.rb +246 -0
  30. data/lib/polars/functions/aggregation/vertical.rb +282 -0
  31. data/lib/polars/functions/as_datatype.rb +248 -0
  32. data/lib/polars/functions/col.rb +47 -0
  33. data/lib/polars/functions/eager.rb +182 -0
  34. data/lib/polars/functions/lazy.rb +1280 -0
  35. data/lib/polars/functions/len.rb +49 -0
  36. data/lib/polars/functions/lit.rb +35 -0
  37. data/lib/polars/functions/random.rb +16 -0
  38. data/lib/polars/functions/range/date_range.rb +103 -0
  39. data/lib/polars/functions/range/int_range.rb +51 -0
  40. data/lib/polars/functions/repeat.rb +144 -0
  41. data/lib/polars/functions/whenthen.rb +96 -0
  42. data/lib/polars/functions.rb +57 -0
  43. data/lib/polars/group_by.rb +548 -0
  44. data/lib/polars/io.rb +890 -0
  45. data/lib/polars/lazy_frame.rb +2833 -0
  46. data/lib/polars/lazy_group_by.rb +84 -0
  47. data/lib/polars/list_expr.rb +791 -0
  48. data/lib/polars/list_name_space.rb +445 -0
  49. data/lib/polars/meta_expr.rb +222 -0
  50. data/lib/polars/name_expr.rb +198 -0
  51. data/lib/polars/plot.rb +109 -0
  52. data/lib/polars/rolling_group_by.rb +37 -0
  53. data/lib/polars/series.rb +4527 -0
  54. data/lib/polars/slice.rb +104 -0
  55. data/lib/polars/sql_context.rb +194 -0
  56. data/lib/polars/string_cache.rb +75 -0
  57. data/lib/polars/string_expr.rb +1519 -0
  58. data/lib/polars/string_name_space.rb +810 -0
  59. data/lib/polars/struct_expr.rb +98 -0
  60. data/lib/polars/struct_name_space.rb +96 -0
  61. data/lib/polars/testing.rb +507 -0
  62. data/lib/polars/utils.rb +422 -0
  63. data/lib/polars/version.rb +4 -0
  64. data/lib/polars/whenthen.rb +83 -0
  65. data/lib/polars-df.rb +1 -0
  66. data/lib/polars.rb +72 -0
  67. metadata +125 -0
@@ -0,0 +1,1444 @@
1
+ module Polars
2
+ # Namespace for datetime related expressions.
3
+ class DateTimeExpr
4
+ # @private
5
+ attr_accessor :_rbexpr
6
+
7
+ # @private
8
+ def initialize(expr)
9
+ self._rbexpr = expr._rbexpr
10
+ end
11
+
12
+ # Divide the date/datetime range into buckets.
13
+ #
14
+ # Each date/datetime is mapped to the start of its bucket.
15
+ #
16
+ # @param every [String]
17
+ # Every interval start and period length
18
+ # @param offset [String]
19
+ # Offset the window
20
+ #
21
+ # @return [Expr]
22
+ #
23
+ # @note
24
+ # The `every` and `offset` argument are created with the
25
+ # the following small string formatting language:
26
+ #
27
+ # 1ns # 1 nanosecond
28
+ # 1us # 1 microsecond
29
+ # 1ms # 1 millisecond
30
+ # 1s # 1 second
31
+ # 1m # 1 minute
32
+ # 1h # 1 hour
33
+ # 1d # 1 day
34
+ # 1w # 1 week
35
+ # 1mo # 1 calendar month
36
+ # 1y # 1 calendar year
37
+ #
38
+ # eg: 3d12h4m25s # 3 days, 12 hours, 4 minutes, and 25 seconds
39
+ #
40
+ # @example
41
+ # start = DateTime.new(2001, 1, 1)
42
+ # stop = DateTime.new(2001, 1, 2)
43
+ # df = Polars.date_range(
44
+ # start, stop, "225m", name: "dates"
45
+ # ).to_frame
46
+ # # =>
47
+ # # shape: (7, 1)
48
+ # # ┌─────────────────────┐
49
+ # # │ dates │
50
+ # # │ --- │
51
+ # # │ datetime[μs] │
52
+ # # ╞═════════════════════╡
53
+ # # │ 2001-01-01 00:00:00 │
54
+ # # │ 2001-01-01 03:45:00 │
55
+ # # │ 2001-01-01 07:30:00 │
56
+ # # │ 2001-01-01 11:15:00 │
57
+ # # │ 2001-01-01 15:00:00 │
58
+ # # │ 2001-01-01 18:45:00 │
59
+ # # │ 2001-01-01 22:30:00 │
60
+ # # └─────────────────────┘
61
+ #
62
+ # @example
63
+ # df.select(Polars.col("dates").dt.truncate("1h"))
64
+ # # =>
65
+ # # shape: (7, 1)
66
+ # # ┌─────────────────────┐
67
+ # # │ dates │
68
+ # # │ --- │
69
+ # # │ datetime[μs] │
70
+ # # ╞═════════════════════╡
71
+ # # │ 2001-01-01 00:00:00 │
72
+ # # │ 2001-01-01 03:00:00 │
73
+ # # │ 2001-01-01 07:00:00 │
74
+ # # │ 2001-01-01 11:00:00 │
75
+ # # │ 2001-01-01 15:00:00 │
76
+ # # │ 2001-01-01 18:00:00 │
77
+ # # │ 2001-01-01 22:00:00 │
78
+ # # └─────────────────────┘
79
+ #
80
+ # @example
81
+ # start = DateTime.new(2001, 1, 1)
82
+ # stop = DateTime.new(2001, 1, 1, 1)
83
+ # df = Polars.date_range(start, stop, "10m", name: "dates").to_frame
84
+ # df.select(["dates", Polars.col("dates").dt.truncate("30m").alias("truncate")])
85
+ # # =>
86
+ # # shape: (7, 2)
87
+ # # ┌─────────────────────┬─────────────────────┐
88
+ # # │ dates ┆ truncate │
89
+ # # │ --- ┆ --- │
90
+ # # │ datetime[μs] ┆ datetime[μs] │
91
+ # # ╞═════════════════════╪═════════════════════╡
92
+ # # │ 2001-01-01 00:00:00 ┆ 2001-01-01 00:00:00 │
93
+ # # │ 2001-01-01 00:10:00 ┆ 2001-01-01 00:00:00 │
94
+ # # │ 2001-01-01 00:20:00 ┆ 2001-01-01 00:00:00 │
95
+ # # │ 2001-01-01 00:30:00 ┆ 2001-01-01 00:30:00 │
96
+ # # │ 2001-01-01 00:40:00 ┆ 2001-01-01 00:30:00 │
97
+ # # │ 2001-01-01 00:50:00 ┆ 2001-01-01 00:30:00 │
98
+ # # │ 2001-01-01 01:00:00 ┆ 2001-01-01 01:00:00 │
99
+ # # └─────────────────────┴─────────────────────┘
100
+ def truncate(every, offset: nil, use_earliest: nil)
101
+ if offset.nil?
102
+ offset = "0ns"
103
+ end
104
+
105
+ if !every.is_a?(Expr)
106
+ every = Utils._timedelta_to_pl_duration(every)
107
+ end
108
+ every = Utils.parse_as_expression(every, str_as_lit: true)
109
+
110
+ Utils.wrap_expr(
111
+ _rbexpr.dt_truncate(
112
+ every,
113
+ Utils._timedelta_to_pl_duration(offset),
114
+ )
115
+ )
116
+ end
117
+
118
+ # Divide the date/datetime range into buckets.
119
+ #
120
+ # Each date/datetime in the first half of the interval
121
+ # is mapped to the start of its bucket.
122
+ # Each date/datetime in the seconod half of the interval
123
+ # is mapped to the end of its bucket.
124
+ #
125
+ # @param every [String]
126
+ # Every interval start and period length
127
+ # @param offset [String]
128
+ # Offset the window
129
+ #
130
+ # @return [Expr]
131
+ #
132
+ # @note
133
+ # The `every` and `offset` argument are created with the
134
+ # the following small string formatting language:
135
+ #
136
+ # 1ns # 1 nanosecond
137
+ # 1us # 1 microsecond
138
+ # 1ms # 1 millisecond
139
+ # 1s # 1 second
140
+ # 1m # 1 minute
141
+ # 1h # 1 hour
142
+ # 1d # 1 day
143
+ # 1w # 1 week
144
+ # 1mo # 1 calendar month
145
+ # 1y # 1 calendar year
146
+ #
147
+ # eg: 3d12h4m25s # 3 days, 12 hours, 4 minutes, and 25 seconds
148
+ #
149
+ # @note
150
+ # This functionality is currently experimental and may
151
+ # change without it being considered a breaking change.
152
+ #
153
+ # @example
154
+ # start = DateTime.new(2001, 1, 1)
155
+ # stop = DateTime.new(2001, 1, 2)
156
+ # df = Polars.date_range(
157
+ # start, stop, "225m", name: "dates"
158
+ # ).to_frame
159
+ # # =>
160
+ # # shape: (7, 1)
161
+ # # ┌─────────────────────┐
162
+ # # │ dates │
163
+ # # │ --- │
164
+ # # │ datetime[μs] │
165
+ # # ╞═════════════════════╡
166
+ # # │ 2001-01-01 00:00:00 │
167
+ # # │ 2001-01-01 03:45:00 │
168
+ # # │ 2001-01-01 07:30:00 │
169
+ # # │ 2001-01-01 11:15:00 │
170
+ # # │ 2001-01-01 15:00:00 │
171
+ # # │ 2001-01-01 18:45:00 │
172
+ # # │ 2001-01-01 22:30:00 │
173
+ # # └─────────────────────┘
174
+ #
175
+ # @example
176
+ # df.select(Polars.col("dates").dt.round("1h"))
177
+ # # =>
178
+ # # shape: (7, 1)
179
+ # # ┌─────────────────────┐
180
+ # # │ dates │
181
+ # # │ --- │
182
+ # # │ datetime[μs] │
183
+ # # ╞═════════════════════╡
184
+ # # │ 2001-01-01 00:00:00 │
185
+ # # │ 2001-01-01 04:00:00 │
186
+ # # │ 2001-01-01 08:00:00 │
187
+ # # │ 2001-01-01 11:00:00 │
188
+ # # │ 2001-01-01 15:00:00 │
189
+ # # │ 2001-01-01 19:00:00 │
190
+ # # │ 2001-01-01 23:00:00 │
191
+ # # └─────────────────────┘
192
+ #
193
+ # @example
194
+ # start = DateTime.new(2001, 1, 1)
195
+ # stop = DateTime.new(2001, 1, 1, 1)
196
+ # df = Polars.date_range(start, stop, "10m", name: "dates").to_frame
197
+ # df.select(["dates", Polars.col("dates").dt.round("30m").alias("round")])
198
+ # # =>
199
+ # # shape: (7, 2)
200
+ # # ┌─────────────────────┬─────────────────────┐
201
+ # # │ dates ┆ round │
202
+ # # │ --- ┆ --- │
203
+ # # │ datetime[μs] ┆ datetime[μs] │
204
+ # # ╞═════════════════════╪═════════════════════╡
205
+ # # │ 2001-01-01 00:00:00 ┆ 2001-01-01 00:00:00 │
206
+ # # │ 2001-01-01 00:10:00 ┆ 2001-01-01 00:00:00 │
207
+ # # │ 2001-01-01 00:20:00 ┆ 2001-01-01 00:30:00 │
208
+ # # │ 2001-01-01 00:30:00 ┆ 2001-01-01 00:30:00 │
209
+ # # │ 2001-01-01 00:40:00 ┆ 2001-01-01 00:30:00 │
210
+ # # │ 2001-01-01 00:50:00 ┆ 2001-01-01 01:00:00 │
211
+ # # │ 2001-01-01 01:00:00 ┆ 2001-01-01 01:00:00 │
212
+ # # └─────────────────────┴─────────────────────┘
213
+ def round(every, offset: nil)
214
+ if offset.nil?
215
+ offset = "0ns"
216
+ end
217
+
218
+ Utils.wrap_expr(
219
+ _rbexpr.dt_round(
220
+ Utils._timedelta_to_pl_duration(every),
221
+ Utils._timedelta_to_pl_duration(offset)
222
+ )
223
+ )
224
+ end
225
+
226
+ # Create a naive Datetime from an existing Date/Datetime expression and a Time.
227
+ #
228
+ # If the underlying expression is a Datetime then its time component is replaced,
229
+ # and if it is a Date then a new Datetime is created by combining the two values.
230
+ #
231
+ # @param time [Object]
232
+ # A Ruby time literal or Polars expression/column that resolves to a time.
233
+ # @param time_unit ["ns", "us", "ms"]
234
+ # Unit of time.
235
+ #
236
+ # @return [Expr]
237
+ def combine(time, time_unit: "us")
238
+ unless time.is_a?(Time) || time.is_a?(Expr)
239
+ raise TypeError, "expected 'time' to be a Ruby time or Polars expression, found #{time}"
240
+ end
241
+ time = Utils.expr_to_lit_or_expr(time)
242
+ Utils.wrap_expr(_rbexpr.dt_combine(time._rbexpr, time_unit))
243
+ end
244
+
245
+ # Format Date/datetime with a formatting rule.
246
+ #
247
+ # See [chrono strftime/strptime](https://docs.rs/chrono/latest/chrono/format/strftime/index.html).
248
+ #
249
+ # @return [Expr]
250
+ def strftime(fmt)
251
+ Utils.wrap_expr(_rbexpr.strftime(fmt))
252
+ end
253
+
254
+ # Extract year from underlying Date representation.
255
+ #
256
+ # Applies to Date and Datetime columns.
257
+ #
258
+ # Returns the year number in the calendar date.
259
+ #
260
+ # @return [Expr]
261
+ #
262
+ # @example
263
+ # start = DateTime.new(2001, 1, 1)
264
+ # stop = DateTime.new(2002, 7, 1)
265
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "180d")})
266
+ # # =>
267
+ # # shape: (4, 1)
268
+ # # ┌─────────────────────┐
269
+ # # │ date │
270
+ # # │ --- │
271
+ # # │ datetime[μs] │
272
+ # # ╞═════════════════════╡
273
+ # # │ 2001-01-01 00:00:00 │
274
+ # # │ 2001-06-30 00:00:00 │
275
+ # # │ 2001-12-27 00:00:00 │
276
+ # # │ 2002-06-25 00:00:00 │
277
+ # # └─────────────────────┘
278
+ #
279
+ # @example
280
+ # df.select(Polars.col("date").dt.year)
281
+ # # =>
282
+ # # shape: (4, 1)
283
+ # # ┌──────┐
284
+ # # │ date │
285
+ # # │ --- │
286
+ # # │ i32 │
287
+ # # ╞══════╡
288
+ # # │ 2001 │
289
+ # # │ 2001 │
290
+ # # │ 2001 │
291
+ # # │ 2002 │
292
+ # # └──────┘
293
+ def year
294
+ Utils.wrap_expr(_rbexpr.year)
295
+ end
296
+
297
+ # Determine whether the year of the underlying date is a leap year.
298
+ #
299
+ # Applies to Date and Datetime columns.
300
+ #
301
+ # @return [Expr]
302
+ #
303
+ # @example
304
+ # start = DateTime.new(2000, 1, 1)
305
+ # stop = DateTime.new(2002, 1, 1)
306
+ # df = Polars::DataFrame.new(
307
+ # {"date" => Polars.date_range(start, stop, "1y")}
308
+ # )
309
+ # df.select(Polars.col("date").dt.is_leap_year)
310
+ # # =>
311
+ # # shape: (3, 1)
312
+ # # ┌───────┐
313
+ # # │ date │
314
+ # # │ --- │
315
+ # # │ bool │
316
+ # # ╞═══════╡
317
+ # # │ true │
318
+ # # │ false │
319
+ # # │ false │
320
+ # # └───────┘
321
+ def is_leap_year
322
+ Utils.wrap_expr(_rbexpr.dt_is_leap_year)
323
+ end
324
+
325
+ # Extract ISO year from underlying Date representation.
326
+ #
327
+ # Applies to Date and Datetime columns.
328
+ #
329
+ # Returns the year number in the ISO standard.
330
+ # This may not correspond with the calendar year.
331
+ #
332
+ # @return [Expr]
333
+ def iso_year
334
+ Utils.wrap_expr(_rbexpr.iso_year)
335
+ end
336
+
337
+ # Extract quarter from underlying Date representation.
338
+ #
339
+ # Applies to Date and Datetime columns.
340
+ #
341
+ # Returns the quarter ranging from 1 to 4.
342
+ #
343
+ # @return [Expr]
344
+ #
345
+ # @example
346
+ # start = DateTime.new(2001, 1, 1)
347
+ # stop = DateTime.new(2002, 6, 1)
348
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "180d")})
349
+ # # =>
350
+ # # shape: (3, 1)
351
+ # # ┌─────────────────────┐
352
+ # # │ date │
353
+ # # │ --- │
354
+ # # │ datetime[μs] │
355
+ # # ╞═════════════════════╡
356
+ # # │ 2001-01-01 00:00:00 │
357
+ # # │ 2001-06-30 00:00:00 │
358
+ # # │ 2001-12-27 00:00:00 │
359
+ # # └─────────────────────┘
360
+ #
361
+ # @example
362
+ # df.select(Polars.col("date").dt.quarter)
363
+ # # =>
364
+ # # shape: (3, 1)
365
+ # # ┌──────┐
366
+ # # │ date │
367
+ # # │ --- │
368
+ # # │ i8 │
369
+ # # ╞══════╡
370
+ # # │ 1 │
371
+ # # │ 2 │
372
+ # # │ 4 │
373
+ # # └──────┘
374
+ def quarter
375
+ Utils.wrap_expr(_rbexpr.quarter)
376
+ end
377
+
378
+ # Extract month from underlying Date representation.
379
+ #
380
+ # Applies to Date and Datetime columns.
381
+ #
382
+ # Returns the month number starting from 1.
383
+ # The return value ranges from 1 to 12.
384
+ #
385
+ # @return [Expr]
386
+ #
387
+ # @example
388
+ # start = DateTime.new(2001, 1, 1)
389
+ # stop = DateTime.new(2001, 4, 1)
390
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "31d")})
391
+ # # =>
392
+ # # shape: (3, 1)
393
+ # # ┌─────────────────────┐
394
+ # # │ date │
395
+ # # │ --- │
396
+ # # │ datetime[μs] │
397
+ # # ╞═════════════════════╡
398
+ # # │ 2001-01-01 00:00:00 │
399
+ # # │ 2001-02-01 00:00:00 │
400
+ # # │ 2001-03-04 00:00:00 │
401
+ # # └─────────────────────┘
402
+ #
403
+ # @example
404
+ # df.select(Polars.col("date").dt.month)
405
+ # # =>
406
+ # # shape: (3, 1)
407
+ # # ┌──────┐
408
+ # # │ date │
409
+ # # │ --- │
410
+ # # │ i8 │
411
+ # # ╞══════╡
412
+ # # │ 1 │
413
+ # # │ 2 │
414
+ # # │ 3 │
415
+ # # └──────┘
416
+ def month
417
+ Utils.wrap_expr(_rbexpr.month)
418
+ end
419
+
420
+ # Extract the week from the underlying Date representation.
421
+ #
422
+ # Applies to Date and Datetime columns.
423
+ #
424
+ # Returns the ISO week number starting from 1.
425
+ # The return value ranges from 1 to 53. (The last week of year differs by years.)
426
+ #
427
+ # @return [Expr]
428
+ #
429
+ # @example
430
+ # start = DateTime.new(2001, 1, 1)
431
+ # stop = DateTime.new(2001, 4, 1)
432
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "31d")})
433
+ # # =>
434
+ # # shape: (3, 1)
435
+ # # ┌─────────────────────┐
436
+ # # │ date │
437
+ # # │ --- │
438
+ # # │ datetime[μs] │
439
+ # # ╞═════════════════════╡
440
+ # # │ 2001-01-01 00:00:00 │
441
+ # # │ 2001-02-01 00:00:00 │
442
+ # # │ 2001-03-04 00:00:00 │
443
+ # # └─────────────────────┘
444
+ #
445
+ # @example
446
+ # df.select(Polars.col("date").dt.week)
447
+ # # =>
448
+ # # shape: (3, 1)
449
+ # # ┌──────┐
450
+ # # │ date │
451
+ # # │ --- │
452
+ # # │ i8 │
453
+ # # ╞══════╡
454
+ # # │ 1 │
455
+ # # │ 5 │
456
+ # # │ 9 │
457
+ # # └──────┘
458
+ def week
459
+ Utils.wrap_expr(_rbexpr.week)
460
+ end
461
+
462
+ # Extract the week day from the underlying Date representation.
463
+ #
464
+ # Applies to Date and Datetime columns.
465
+ #
466
+ # Returns the ISO weekday number where monday = 1 and sunday = 7
467
+ #
468
+ # @return [Expr]
469
+ #
470
+ # @example
471
+ # start = DateTime.new(2001, 1, 1)
472
+ # stop = DateTime.new(2001, 1, 9)
473
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "3d")})
474
+ # # =>
475
+ # # shape: (3, 1)
476
+ # # ┌─────────────────────┐
477
+ # # │ date │
478
+ # # │ --- │
479
+ # # │ datetime[μs] │
480
+ # # ╞═════════════════════╡
481
+ # # │ 2001-01-01 00:00:00 │
482
+ # # │ 2001-01-04 00:00:00 │
483
+ # # │ 2001-01-07 00:00:00 │
484
+ # # └─────────────────────┘
485
+ #
486
+ # @example
487
+ # df.select(
488
+ # [
489
+ # Polars.col("date").dt.weekday.alias("weekday"),
490
+ # Polars.col("date").dt.day.alias("day_of_month"),
491
+ # Polars.col("date").dt.ordinal_day.alias("day_of_year")
492
+ # ]
493
+ # )
494
+ # # =>
495
+ # # shape: (3, 3)
496
+ # # ┌─────────┬──────────────┬─────────────┐
497
+ # # │ weekday ┆ day_of_month ┆ day_of_year │
498
+ # # │ --- ┆ --- ┆ --- │
499
+ # # │ i8 ┆ i8 ┆ i16 │
500
+ # # ╞═════════╪══════════════╪═════════════╡
501
+ # # │ 1 ┆ 1 ┆ 1 │
502
+ # # │ 4 ┆ 4 ┆ 4 │
503
+ # # │ 7 ┆ 7 ┆ 7 │
504
+ # # └─────────┴──────────────┴─────────────┘
505
+ def weekday
506
+ Utils.wrap_expr(_rbexpr.weekday)
507
+ end
508
+
509
+ # Extract day from underlying Date representation.
510
+ #
511
+ # Applies to Date and Datetime columns.
512
+ #
513
+ # Returns the day of month starting from 1.
514
+ # The return value ranges from 1 to 31. (The last day of month differs by months.)
515
+ #
516
+ # @return [Expr]
517
+ #
518
+ # @example
519
+ # start = DateTime.new(2001, 1, 1)
520
+ # stop = DateTime.new(2001, 1, 9)
521
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "3d")})
522
+ # # =>
523
+ # # shape: (3, 1)
524
+ # # ┌─────────────────────┐
525
+ # # │ date │
526
+ # # │ --- │
527
+ # # │ datetime[μs] │
528
+ # # ╞═════════════════════╡
529
+ # # │ 2001-01-01 00:00:00 │
530
+ # # │ 2001-01-04 00:00:00 │
531
+ # # │ 2001-01-07 00:00:00 │
532
+ # # └─────────────────────┘
533
+ #
534
+ # @example
535
+ # df.select(
536
+ # [
537
+ # Polars.col("date").dt.weekday.alias("weekday"),
538
+ # Polars.col("date").dt.day.alias("day_of_month"),
539
+ # Polars.col("date").dt.ordinal_day.alias("day_of_year")
540
+ # ]
541
+ # )
542
+ # # =>
543
+ # # shape: (3, 3)
544
+ # # ┌─────────┬──────────────┬─────────────┐
545
+ # # │ weekday ┆ day_of_month ┆ day_of_year │
546
+ # # │ --- ┆ --- ┆ --- │
547
+ # # │ i8 ┆ i8 ┆ i16 │
548
+ # # ╞═════════╪══════════════╪═════════════╡
549
+ # # │ 1 ┆ 1 ┆ 1 │
550
+ # # │ 4 ┆ 4 ┆ 4 │
551
+ # # │ 7 ┆ 7 ┆ 7 │
552
+ # # └─────────┴──────────────┴─────────────┘
553
+ def day
554
+ Utils.wrap_expr(_rbexpr.day)
555
+ end
556
+
557
+ # Extract ordinal day from underlying Date representation.
558
+ #
559
+ # Applies to Date and Datetime columns.
560
+ #
561
+ # Returns the day of month starting from 1.
562
+ # The return value ranges from 1 to 31. (The last day of month differs by months.)
563
+ #
564
+ # @return [Expr]
565
+ #
566
+ # @example
567
+ # start = DateTime.new(2001, 1, 1)
568
+ # stop = DateTime.new(2001, 1, 9)
569
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "3d")})
570
+ # # =>
571
+ # # shape: (3, 1)
572
+ # # ┌─────────────────────┐
573
+ # # │ date │
574
+ # # │ --- │
575
+ # # │ datetime[μs] │
576
+ # # ╞═════════════════════╡
577
+ # # │ 2001-01-01 00:00:00 │
578
+ # # │ 2001-01-04 00:00:00 │
579
+ # # │ 2001-01-07 00:00:00 │
580
+ # # └─────────────────────┘
581
+ #
582
+ # @example
583
+ # df.select(
584
+ # [
585
+ # Polars.col("date").dt.weekday.alias("weekday"),
586
+ # Polars.col("date").dt.day.alias("day_of_month"),
587
+ # Polars.col("date").dt.ordinal_day.alias("day_of_year")
588
+ # ]
589
+ # )
590
+ # # =>
591
+ # # shape: (3, 3)
592
+ # # ┌─────────┬──────────────┬─────────────┐
593
+ # # │ weekday ┆ day_of_month ┆ day_of_year │
594
+ # # │ --- ┆ --- ┆ --- │
595
+ # # │ i8 ┆ i8 ┆ i16 │
596
+ # # ╞═════════╪══════════════╪═════════════╡
597
+ # # │ 1 ┆ 1 ┆ 1 │
598
+ # # │ 4 ┆ 4 ┆ 4 │
599
+ # # │ 7 ┆ 7 ┆ 7 │
600
+ # # └─────────┴──────────────┴─────────────┘
601
+ def ordinal_day
602
+ Utils.wrap_expr(_rbexpr.ordinal_day)
603
+ end
604
+
605
+ # Time
606
+ #
607
+ # @return [Expr]
608
+ def time
609
+ Utils.wrap_expr(_rbexpr.dt_time)
610
+ end
611
+
612
+ # Date
613
+ #
614
+ # @return [Expr]
615
+ def date
616
+ Utils.wrap_expr(_rbexpr.dt_date)
617
+ end
618
+
619
+ # Datetime
620
+ #
621
+ # @return [Expr]
622
+ def datetime
623
+ Utils.wrap_expr(_rbexpr.dt_datetime)
624
+ end
625
+
626
+ # Extract hour from underlying DateTime representation.
627
+ #
628
+ # Applies to Datetime columns.
629
+ #
630
+ # Returns the hour number from 0 to 23.
631
+ #
632
+ # @return [Expr]
633
+ #
634
+ # @example
635
+ # start = DateTime.new(2001, 1, 1)
636
+ # stop = DateTime.new(2001, 1, 2)
637
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "12h")})
638
+ # # =>
639
+ # # shape: (3, 1)
640
+ # # ┌─────────────────────┐
641
+ # # │ date │
642
+ # # │ --- │
643
+ # # │ datetime[μs] │
644
+ # # ╞═════════════════════╡
645
+ # # │ 2001-01-01 00:00:00 │
646
+ # # │ 2001-01-01 12:00:00 │
647
+ # # │ 2001-01-02 00:00:00 │
648
+ # # └─────────────────────┘
649
+ #
650
+ # @example
651
+ # df.select(Polars.col("date").dt.hour)
652
+ # # =>
653
+ # # shape: (3, 1)
654
+ # # ┌──────┐
655
+ # # │ date │
656
+ # # │ --- │
657
+ # # │ i8 │
658
+ # # ╞══════╡
659
+ # # │ 0 │
660
+ # # │ 12 │
661
+ # # │ 0 │
662
+ # # └──────┘
663
+ def hour
664
+ Utils.wrap_expr(_rbexpr.hour)
665
+ end
666
+
667
+ # Extract minutes from underlying DateTime representation.
668
+ #
669
+ # Applies to Datetime columns.
670
+ #
671
+ # Returns the minute number from 0 to 59.
672
+ #
673
+ # @return [Expr]
674
+ #
675
+ # @example
676
+ # start = DateTime.new(2001, 1, 1)
677
+ # stop = DateTime.new(2001, 1, 1, 0, 4, 0)
678
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "2m")})
679
+ # # =>
680
+ # # shape: (3, 1)
681
+ # # ┌─────────────────────┐
682
+ # # │ date │
683
+ # # │ --- │
684
+ # # │ datetime[μs] │
685
+ # # ╞═════════════════════╡
686
+ # # │ 2001-01-01 00:00:00 │
687
+ # # │ 2001-01-01 00:02:00 │
688
+ # # │ 2001-01-01 00:04:00 │
689
+ # # └─────────────────────┘
690
+ #
691
+ # @example
692
+ # df.select(Polars.col("date").dt.minute)
693
+ # # =>
694
+ # # shape: (3, 1)
695
+ # # ┌──────┐
696
+ # # │ date │
697
+ # # │ --- │
698
+ # # │ i8 │
699
+ # # ╞══════╡
700
+ # # │ 0 │
701
+ # # │ 2 │
702
+ # # │ 4 │
703
+ # # └──────┘
704
+ def minute
705
+ Utils.wrap_expr(_rbexpr.minute)
706
+ end
707
+
708
+ # Extract seconds from underlying DateTime representation.
709
+ #
710
+ # Applies to Datetime columns.
711
+ #
712
+ # Returns the integer second number from 0 to 59, or a floating
713
+ # point number from 0 < 60 if `fractional: true` that includes
714
+ # any milli/micro/nanosecond component.
715
+ #
716
+ # @return [Expr]
717
+ #
718
+ # @example
719
+ # df = Polars::DataFrame.new(
720
+ # {
721
+ # "date" => Polars.date_range(
722
+ # DateTime.new(2001, 1, 1, 0, 0, 0.456789),
723
+ # DateTime.new(2001, 1, 1, 0, 0, 6),
724
+ # "2s654321us"
725
+ # )
726
+ # }
727
+ # )
728
+ # # =>
729
+ # # shape: (3, 1)
730
+ # # ┌────────────────────────────┐
731
+ # # │ date │
732
+ # # │ --- │
733
+ # # │ datetime[μs] │
734
+ # # ╞════════════════════════════╡
735
+ # # │ 2001-01-01 00:00:00.456789 │
736
+ # # │ 2001-01-01 00:00:03.111110 │
737
+ # # │ 2001-01-01 00:00:05.765431 │
738
+ # # └────────────────────────────┘
739
+ #
740
+ # @example
741
+ # df.select(Polars.col("date").dt.second.alias("secs"))
742
+ # # =>
743
+ # # shape: (3, 1)
744
+ # # ┌──────┐
745
+ # # │ secs │
746
+ # # │ --- │
747
+ # # │ i8 │
748
+ # # ╞══════╡
749
+ # # │ 0 │
750
+ # # │ 3 │
751
+ # # │ 5 │
752
+ # # └──────┘
753
+ #
754
+ # df.select(Polars.col("date").dt.second(fractional: true).alias("secs"))
755
+ # # =>
756
+ # # shape: (3, 1)
757
+ # # ┌──────────┐
758
+ # # │ secs │
759
+ # # │ --- │
760
+ # # │ f64 │
761
+ # # ╞══════════╡
762
+ # # │ 0.456789 │
763
+ # # │ 3.11111 │
764
+ # # │ 5.765431 │
765
+ # # └──────────┘
766
+ #
767
+ # @example
768
+ # start = DateTime.new(2001, 1, 1)
769
+ # stop = DateTime.new(2001, 1, 1, 0, 0, 4)
770
+ # df = Polars::DataFrame.new(
771
+ # {"date" => Polars.date_range(start, stop, "2s")}
772
+ # )
773
+ # # =>
774
+ # # shape: (3, 1)
775
+ # # ┌─────────────────────┐
776
+ # # │ date │
777
+ # # │ --- │
778
+ # # │ datetime[μs] │
779
+ # # ╞═════════════════════╡
780
+ # # │ 2001-01-01 00:00:00 │
781
+ # # │ 2001-01-01 00:00:02 │
782
+ # # │ 2001-01-01 00:00:04 │
783
+ # # └─────────────────────┘
784
+ #
785
+ # @example
786
+ # df.select(Polars.col("date").dt.second)
787
+ # # =>
788
+ # # shape: (3, 1)
789
+ # # ┌──────┐
790
+ # # │ date │
791
+ # # │ --- │
792
+ # # │ i8 │
793
+ # # ╞══════╡
794
+ # # │ 0 │
795
+ # # │ 2 │
796
+ # # │ 4 │
797
+ # # └──────┘
798
+ def second(fractional: false)
799
+ sec = Utils.wrap_expr(_rbexpr.second)
800
+ if fractional
801
+ sec + (Utils.wrap_expr(_rbexpr.nanosecond) / Utils.lit(1_000_000_000.0))
802
+ else
803
+ sec
804
+ end
805
+ end
806
+
807
+ # Extract milliseconds from underlying DateTime representation.
808
+ #
809
+ # Applies to Datetime columns.
810
+ #
811
+ # @return [Expr]
812
+ def millisecond
813
+ Utils.wrap_expr(_rbexpr.millisecond)
814
+ end
815
+
816
+ # Extract microseconds from underlying DateTime representation.
817
+ #
818
+ # Applies to Datetime columns.
819
+ #
820
+ # @return [Expr]
821
+ def microsecond
822
+ Utils.wrap_expr(_rbexpr.microsecond)
823
+ end
824
+
825
+ # Extract nanoseconds from underlying DateTime representation.
826
+ #
827
+ # Applies to Datetime columns.
828
+ #
829
+ # @return [Expr]
830
+ def nanosecond
831
+ Utils.wrap_expr(_rbexpr.nanosecond)
832
+ end
833
+
834
+ # Get the time passed since the Unix EPOCH in the give time unit.
835
+ #
836
+ # @param tu ["us", "ns", "ms", "s", "d"]
837
+ # Time unit.
838
+ #
839
+ # @return [Expr]
840
+ #
841
+ # @example
842
+ # start = DateTime.new(2001, 1, 1)
843
+ # stop = DateTime.new(2001, 1, 3)
844
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "1d")})
845
+ # df.select(
846
+ # [
847
+ # Polars.col("date"),
848
+ # Polars.col("date").dt.epoch.alias("epoch_ns"),
849
+ # Polars.col("date").dt.epoch("s").alias("epoch_s")
850
+ # ]
851
+ # )
852
+ # # =>
853
+ # # shape: (3, 3)
854
+ # # ┌─────────────────────┬─────────────────┬───────────┐
855
+ # # │ date ┆ epoch_ns ┆ epoch_s │
856
+ # # │ --- ┆ --- ┆ --- │
857
+ # # │ datetime[μs] ┆ i64 ┆ i64 │
858
+ # # ╞═════════════════════╪═════════════════╪═══════════╡
859
+ # # │ 2001-01-01 00:00:00 ┆ 978307200000000 ┆ 978307200 │
860
+ # # │ 2001-01-02 00:00:00 ┆ 978393600000000 ┆ 978393600 │
861
+ # # │ 2001-01-03 00:00:00 ┆ 978480000000000 ┆ 978480000 │
862
+ # # └─────────────────────┴─────────────────┴───────────┘
863
+ def epoch(tu = "us")
864
+ if Utils::DTYPE_TEMPORAL_UNITS.include?(tu)
865
+ timestamp(tu)
866
+ elsif tu == "s"
867
+ Utils.wrap_expr(_rbexpr.dt_epoch_seconds)
868
+ elsif tu == "d"
869
+ Utils.wrap_expr(_rbexpr).cast(:date).cast(:i32)
870
+ else
871
+ raise ArgumentError, "tu must be one of {{'ns', 'us', 'ms', 's', 'd'}}, got #{tu}"
872
+ end
873
+ end
874
+
875
+ # Return a timestamp in the given time unit.
876
+ #
877
+ # @param tu ["us", "ns", "ms"]
878
+ # Time unit.
879
+ #
880
+ # @return [Expr]
881
+ #
882
+ # @example
883
+ # start = DateTime.new(2001, 1, 1)
884
+ # stop = DateTime.new(2001, 1, 3)
885
+ # df = Polars::DataFrame.new({"date" => Polars.date_range(start, stop, "1d")})
886
+ # df.select(
887
+ # [
888
+ # Polars.col("date"),
889
+ # Polars.col("date").dt.timestamp.alias("timestamp_ns"),
890
+ # Polars.col("date").dt.timestamp("ms").alias("timestamp_ms")
891
+ # ]
892
+ # )
893
+ # # =>
894
+ # # shape: (3, 3)
895
+ # # ┌─────────────────────┬─────────────────┬──────────────┐
896
+ # # │ date ┆ timestamp_ns ┆ timestamp_ms │
897
+ # # │ --- ┆ --- ┆ --- │
898
+ # # │ datetime[μs] ┆ i64 ┆ i64 │
899
+ # # ╞═════════════════════╪═════════════════╪══════════════╡
900
+ # # │ 2001-01-01 00:00:00 ┆ 978307200000000 ┆ 978307200000 │
901
+ # # │ 2001-01-02 00:00:00 ┆ 978393600000000 ┆ 978393600000 │
902
+ # # │ 2001-01-03 00:00:00 ┆ 978480000000000 ┆ 978480000000 │
903
+ # # └─────────────────────┴─────────────────┴──────────────┘
904
+ def timestamp(tu = "us")
905
+ Utils.wrap_expr(_rbexpr.timestamp(tu))
906
+ end
907
+
908
+ # Set time unit of a Series of dtype Datetime or Duration.
909
+ #
910
+ # This does not modify underlying data, and should be used to fix an incorrect
911
+ # time unit.
912
+ #
913
+ # @param tu ["ns", "us", "ms"]
914
+ # Time unit for the `Datetime` Series.
915
+ #
916
+ # @return [Expr]
917
+ #
918
+ # @example
919
+ # df = Polars::DataFrame.new(
920
+ # {
921
+ # "date" => Polars.date_range(
922
+ # DateTime.new(2001, 1, 1), DateTime.new(2001, 1, 3), "1d", time_unit: "ns"
923
+ # )
924
+ # }
925
+ # )
926
+ # df.select(
927
+ # [
928
+ # Polars.col("date"),
929
+ # Polars.col("date").dt.with_time_unit("us").alias("tu_us")
930
+ # ]
931
+ # )
932
+ # # =>
933
+ # # shape: (3, 2)
934
+ # # ┌─────────────────────┬───────────────────────┐
935
+ # # │ date ┆ tu_us │
936
+ # # │ --- ┆ --- │
937
+ # # │ datetime[ns] ┆ datetime[μs] │
938
+ # # ╞═════════════════════╪═══════════════════════╡
939
+ # # │ 2001-01-01 00:00:00 ┆ +32971-04-28 00:00:00 │
940
+ # # │ 2001-01-02 00:00:00 ┆ +32974-01-22 00:00:00 │
941
+ # # │ 2001-01-03 00:00:00 ┆ +32976-10-18 00:00:00 │
942
+ # # └─────────────────────┴───────────────────────┘
943
+ def with_time_unit(tu)
944
+ Utils.wrap_expr(_rbexpr.dt_with_time_unit(tu))
945
+ end
946
+
947
+ # Cast the underlying data to another time unit. This may lose precision.
948
+ #
949
+ # @param tu ["ns", "us", "ms"]
950
+ # Time unit for the `Datetime` Series.
951
+ #
952
+ # @return [Expr]
953
+ #
954
+ # @example
955
+ # df = Polars::DataFrame.new(
956
+ # {
957
+ # "date" => Polars.date_range(
958
+ # DateTime.new(2001, 1, 1), DateTime.new(2001, 1, 3), "1d"
959
+ # )
960
+ # }
961
+ # )
962
+ # df.select(
963
+ # [
964
+ # Polars.col("date"),
965
+ # Polars.col("date").dt.cast_time_unit("ms").alias("tu_ms"),
966
+ # Polars.col("date").dt.cast_time_unit("ns").alias("tu_ns")
967
+ # ]
968
+ # )
969
+ # # =>
970
+ # # shape: (3, 3)
971
+ # # ┌─────────────────────┬─────────────────────┬─────────────────────┐
972
+ # # │ date ┆ tu_ms ┆ tu_ns │
973
+ # # │ --- ┆ --- ┆ --- │
974
+ # # │ datetime[μs] ┆ datetime[ms] ┆ datetime[ns] │
975
+ # # ╞═════════════════════╪═════════════════════╪═════════════════════╡
976
+ # # │ 2001-01-01 00:00:00 ┆ 2001-01-01 00:00:00 ┆ 2001-01-01 00:00:00 │
977
+ # # │ 2001-01-02 00:00:00 ┆ 2001-01-02 00:00:00 ┆ 2001-01-02 00:00:00 │
978
+ # # │ 2001-01-03 00:00:00 ┆ 2001-01-03 00:00:00 ┆ 2001-01-03 00:00:00 │
979
+ # # └─────────────────────┴─────────────────────┴─────────────────────┘
980
+ def cast_time_unit(tu)
981
+ Utils.wrap_expr(_rbexpr.dt_cast_time_unit(tu))
982
+ end
983
+
984
+ # Set time zone for a Series of type Datetime.
985
+ #
986
+ # @param tz [String]
987
+ # Time zone for the `Datetime` Series.
988
+ #
989
+ # @return [Expr]
990
+ #
991
+ # @example
992
+ # df = Polars::DataFrame.new(
993
+ # {
994
+ # "date" => Polars.date_range(
995
+ # DateTime.new(2020, 3, 1),
996
+ # DateTime.new(2020, 5, 1),
997
+ # "1mo",
998
+ # time_zone: "UTC"
999
+ # )
1000
+ # }
1001
+ # )
1002
+ # df.select(
1003
+ # [
1004
+ # Polars.col("date"),
1005
+ # Polars.col("date")
1006
+ # .dt.convert_time_zone("Europe/London")
1007
+ # .alias("London")
1008
+ # ]
1009
+ # )
1010
+ # # =>
1011
+ # # shape: (3, 2)
1012
+ # # ┌─────────────────────────┬─────────────────────────────┐
1013
+ # # │ date ┆ London │
1014
+ # # │ --- ┆ --- │
1015
+ # # │ datetime[μs, UTC] ┆ datetime[μs, Europe/London] │
1016
+ # # ╞═════════════════════════╪═════════════════════════════╡
1017
+ # # │ 2020-03-01 00:00:00 UTC ┆ 2020-03-01 00:00:00 GMT │
1018
+ # # │ 2020-04-01 00:00:00 UTC ┆ 2020-04-01 01:00:00 BST │
1019
+ # # │ 2020-05-01 00:00:00 UTC ┆ 2020-05-01 01:00:00 BST │
1020
+ # # └─────────────────────────┴─────────────────────────────┘
1021
+ def convert_time_zone(tz)
1022
+ Utils.wrap_expr(_rbexpr.dt_convert_time_zone(tz))
1023
+ end
1024
+
1025
+ # Cast time zone for a Series of type Datetime.
1026
+ #
1027
+ # Different from `convert_time_zone`, this will also modify
1028
+ # the underlying timestamp,
1029
+ #
1030
+ # @param time_zone [String]
1031
+ # Time zone for the `Datetime` Series. Pass `nil` to unset time zone.
1032
+ # @param use_earliest [Boolean]
1033
+ # Determine how to deal with ambiguous datetimes.
1034
+ # @param ambiguous [String]
1035
+ # Determine how to deal with ambiguous datetimes.
1036
+ # @param non_existent [String]
1037
+ # Determine how to deal with non-existent datetimes.
1038
+ #
1039
+ # @return [Expr]
1040
+ def replace_time_zone(time_zone, use_earliest: nil, ambiguous: "raise", non_existent: "raise")
1041
+ ambiguous = Utils.rename_use_earliest_to_ambiguous(use_earliest, ambiguous)
1042
+ ambiguous = Polars.lit(ambiguous) unless ambiguous.is_a?(Expr)
1043
+ Utils.wrap_expr(_rbexpr.dt_replace_time_zone(time_zone, ambiguous._rbexpr, non_existent))
1044
+ end
1045
+
1046
+ # Extract the days from a Duration type.
1047
+ #
1048
+ # @return [Expr]
1049
+ #
1050
+ # @example
1051
+ # df = Polars::DataFrame.new(
1052
+ # {
1053
+ # "date" => Polars.date_range(
1054
+ # DateTime.new(2020, 3, 1), DateTime.new(2020, 5, 1), "1mo"
1055
+ # )
1056
+ # }
1057
+ # )
1058
+ # df.select(
1059
+ # [
1060
+ # Polars.col("date"),
1061
+ # Polars.col("date").diff.dt.days.alias("days_diff")
1062
+ # ]
1063
+ # )
1064
+ # # =>
1065
+ # # shape: (3, 2)
1066
+ # # ┌─────────────────────┬───────────┐
1067
+ # # │ date ┆ days_diff │
1068
+ # # │ --- ┆ --- │
1069
+ # # │ datetime[μs] ┆ i64 │
1070
+ # # ╞═════════════════════╪═══════════╡
1071
+ # # │ 2020-03-01 00:00:00 ┆ null │
1072
+ # # │ 2020-04-01 00:00:00 ┆ 31 │
1073
+ # # │ 2020-05-01 00:00:00 ┆ 30 │
1074
+ # # └─────────────────────┴───────────┘
1075
+ def total_days
1076
+ Utils.wrap_expr(_rbexpr.dt_total_days)
1077
+ end
1078
+ alias_method :days, :total_days
1079
+
1080
+ # Extract the hours from a Duration type.
1081
+ #
1082
+ # @return [Expr]
1083
+ #
1084
+ # @example
1085
+ # df = Polars::DataFrame.new(
1086
+ # {
1087
+ # "date" => Polars.date_range(
1088
+ # DateTime.new(2020, 1, 1), DateTime.new(2020, 1, 4), "1d"
1089
+ # )
1090
+ # }
1091
+ # )
1092
+ # df.select(
1093
+ # [
1094
+ # Polars.col("date"),
1095
+ # Polars.col("date").diff.dt.hours.alias("hours_diff")
1096
+ # ]
1097
+ # )
1098
+ # # =>
1099
+ # # shape: (4, 2)
1100
+ # # ┌─────────────────────┬────────────┐
1101
+ # # │ date ┆ hours_diff │
1102
+ # # │ --- ┆ --- │
1103
+ # # │ datetime[μs] ┆ i64 │
1104
+ # # ╞═════════════════════╪════════════╡
1105
+ # # │ 2020-01-01 00:00:00 ┆ null │
1106
+ # # │ 2020-01-02 00:00:00 ┆ 24 │
1107
+ # # │ 2020-01-03 00:00:00 ┆ 24 │
1108
+ # # │ 2020-01-04 00:00:00 ┆ 24 │
1109
+ # # └─────────────────────┴────────────┘
1110
+ def total_hours
1111
+ Utils.wrap_expr(_rbexpr.dt_total_hours)
1112
+ end
1113
+ alias_method :hours, :total_hours
1114
+
1115
+ # Extract the minutes from a Duration type.
1116
+ #
1117
+ # @return [Expr]
1118
+ #
1119
+ # @example
1120
+ # df = Polars::DataFrame.new(
1121
+ # {
1122
+ # "date" => Polars.date_range(
1123
+ # DateTime.new(2020, 1, 1), DateTime.new(2020, 1, 4), "1d"
1124
+ # )
1125
+ # }
1126
+ # )
1127
+ # df.select(
1128
+ # [
1129
+ # Polars.col("date"),
1130
+ # Polars.col("date").diff.dt.minutes.alias("minutes_diff")
1131
+ # ]
1132
+ # )
1133
+ # # =>
1134
+ # # shape: (4, 2)
1135
+ # # ┌─────────────────────┬──────────────┐
1136
+ # # │ date ┆ minutes_diff │
1137
+ # # │ --- ┆ --- │
1138
+ # # │ datetime[μs] ┆ i64 │
1139
+ # # ╞═════════════════════╪══════════════╡
1140
+ # # │ 2020-01-01 00:00:00 ┆ null │
1141
+ # # │ 2020-01-02 00:00:00 ┆ 1440 │
1142
+ # # │ 2020-01-03 00:00:00 ┆ 1440 │
1143
+ # # │ 2020-01-04 00:00:00 ┆ 1440 │
1144
+ # # └─────────────────────┴──────────────┘
1145
+ def total_minutes
1146
+ Utils.wrap_expr(_rbexpr.dt_total_minutes)
1147
+ end
1148
+ alias_method :minutes, :total_minutes
1149
+
1150
+ # Extract the seconds from a Duration type.
1151
+ #
1152
+ # @return [Expr]
1153
+ #
1154
+ # @example
1155
+ # df = Polars::DataFrame.new(
1156
+ # {
1157
+ # "date" => Polars.date_range(
1158
+ # DateTime.new(2020, 1, 1), DateTime.new(2020, 1, 1, 0, 4, 0), "1m"
1159
+ # )
1160
+ # }
1161
+ # )
1162
+ # df.select(
1163
+ # [
1164
+ # Polars.col("date"),
1165
+ # Polars.col("date").diff.dt.seconds.alias("seconds_diff")
1166
+ # ]
1167
+ # )
1168
+ # # =>
1169
+ # # shape: (5, 2)
1170
+ # # ┌─────────────────────┬──────────────┐
1171
+ # # │ date ┆ seconds_diff │
1172
+ # # │ --- ┆ --- │
1173
+ # # │ datetime[μs] ┆ i64 │
1174
+ # # ╞═════════════════════╪══════════════╡
1175
+ # # │ 2020-01-01 00:00:00 ┆ null │
1176
+ # # │ 2020-01-01 00:01:00 ┆ 60 │
1177
+ # # │ 2020-01-01 00:02:00 ┆ 60 │
1178
+ # # │ 2020-01-01 00:03:00 ┆ 60 │
1179
+ # # │ 2020-01-01 00:04:00 ┆ 60 │
1180
+ # # └─────────────────────┴──────────────┘
1181
+ def total_seconds
1182
+ Utils.wrap_expr(_rbexpr.dt_total_seconds)
1183
+ end
1184
+ alias_method :seconds, :total_seconds
1185
+
1186
+ # Extract the milliseconds from a Duration type.
1187
+ #
1188
+ # @return [Expr]
1189
+ #
1190
+ # @example
1191
+ # df = Polars::DataFrame.new(
1192
+ # {
1193
+ # "date" => Polars.date_range(
1194
+ # DateTime.new(2020, 1, 1), DateTime.new(2020, 1, 1, 0, 0, 1), "1ms"
1195
+ # )
1196
+ # }
1197
+ # )
1198
+ # df.select(
1199
+ # [
1200
+ # Polars.col("date"),
1201
+ # Polars.col("date").diff.dt.milliseconds.alias("milliseconds_diff")
1202
+ # ]
1203
+ # )
1204
+ # # =>
1205
+ # # shape: (1_001, 2)
1206
+ # # ┌─────────────────────────┬───────────────────┐
1207
+ # # │ date ┆ milliseconds_diff │
1208
+ # # │ --- ┆ --- │
1209
+ # # │ datetime[μs] ┆ i64 │
1210
+ # # ╞═════════════════════════╪═══════════════════╡
1211
+ # # │ 2020-01-01 00:00:00 ┆ null │
1212
+ # # │ 2020-01-01 00:00:00.001 ┆ 1 │
1213
+ # # │ 2020-01-01 00:00:00.002 ┆ 1 │
1214
+ # # │ 2020-01-01 00:00:00.003 ┆ 1 │
1215
+ # # │ 2020-01-01 00:00:00.004 ┆ 1 │
1216
+ # # │ … ┆ … │
1217
+ # # │ 2020-01-01 00:00:00.996 ┆ 1 │
1218
+ # # │ 2020-01-01 00:00:00.997 ┆ 1 │
1219
+ # # │ 2020-01-01 00:00:00.998 ┆ 1 │
1220
+ # # │ 2020-01-01 00:00:00.999 ┆ 1 │
1221
+ # # │ 2020-01-01 00:00:01 ┆ 1 │
1222
+ # # └─────────────────────────┴───────────────────┘
1223
+ def total_milliseconds
1224
+ Utils.wrap_expr(_rbexpr.dt_total_milliseconds)
1225
+ end
1226
+ alias_method :milliseconds, :total_milliseconds
1227
+
1228
+ # Extract the microseconds from a Duration type.
1229
+ #
1230
+ # @return [Expr]
1231
+ #
1232
+ # @example
1233
+ # df = Polars::DataFrame.new(
1234
+ # {
1235
+ # "date" => Polars.date_range(
1236
+ # DateTime.new(2020, 1, 1), DateTime.new(2020, 1, 1, 0, 0, 1), "1ms"
1237
+ # )
1238
+ # }
1239
+ # )
1240
+ # df.select(
1241
+ # [
1242
+ # Polars.col("date"),
1243
+ # Polars.col("date").diff.dt.microseconds.alias("microseconds_diff")
1244
+ # ]
1245
+ # )
1246
+ # # =>
1247
+ # # shape: (1_001, 2)
1248
+ # # ┌─────────────────────────┬───────────────────┐
1249
+ # # │ date ┆ microseconds_diff │
1250
+ # # │ --- ┆ --- │
1251
+ # # │ datetime[μs] ┆ i64 │
1252
+ # # ╞═════════════════════════╪═══════════════════╡
1253
+ # # │ 2020-01-01 00:00:00 ┆ null │
1254
+ # # │ 2020-01-01 00:00:00.001 ┆ 1000 │
1255
+ # # │ 2020-01-01 00:00:00.002 ┆ 1000 │
1256
+ # # │ 2020-01-01 00:00:00.003 ┆ 1000 │
1257
+ # # │ 2020-01-01 00:00:00.004 ┆ 1000 │
1258
+ # # │ … ┆ … │
1259
+ # # │ 2020-01-01 00:00:00.996 ┆ 1000 │
1260
+ # # │ 2020-01-01 00:00:00.997 ┆ 1000 │
1261
+ # # │ 2020-01-01 00:00:00.998 ┆ 1000 │
1262
+ # # │ 2020-01-01 00:00:00.999 ┆ 1000 │
1263
+ # # │ 2020-01-01 00:00:01 ┆ 1000 │
1264
+ # # └─────────────────────────┴───────────────────┘
1265
+ def total_microseconds
1266
+ Utils.wrap_expr(_rbexpr.dt_total_microseconds)
1267
+ end
1268
+ alias_method :microseconds, :total_microseconds
1269
+
1270
+ # Extract the nanoseconds from a Duration type.
1271
+ #
1272
+ # @return [Expr]
1273
+ #
1274
+ # @example
1275
+ # df = Polars::DataFrame.new(
1276
+ # {
1277
+ # "date" => Polars.date_range(
1278
+ # DateTime.new(2020, 1, 1), DateTime.new(2020, 1, 1, 0, 0, 1), "1ms"
1279
+ # )
1280
+ # }
1281
+ # )
1282
+ # df.select(
1283
+ # [
1284
+ # Polars.col("date"),
1285
+ # Polars.col("date").diff.dt.nanoseconds.alias("nanoseconds_diff")
1286
+ # ]
1287
+ # )
1288
+ # # =>
1289
+ # # shape: (1_001, 2)
1290
+ # # ┌─────────────────────────┬──────────────────┐
1291
+ # # │ date ┆ nanoseconds_diff │
1292
+ # # │ --- ┆ --- │
1293
+ # # │ datetime[μs] ┆ i64 │
1294
+ # # ╞═════════════════════════╪══════════════════╡
1295
+ # # │ 2020-01-01 00:00:00 ┆ null │
1296
+ # # │ 2020-01-01 00:00:00.001 ┆ 1000000 │
1297
+ # # │ 2020-01-01 00:00:00.002 ┆ 1000000 │
1298
+ # # │ 2020-01-01 00:00:00.003 ┆ 1000000 │
1299
+ # # │ 2020-01-01 00:00:00.004 ┆ 1000000 │
1300
+ # # │ … ┆ … │
1301
+ # # │ 2020-01-01 00:00:00.996 ┆ 1000000 │
1302
+ # # │ 2020-01-01 00:00:00.997 ┆ 1000000 │
1303
+ # # │ 2020-01-01 00:00:00.998 ┆ 1000000 │
1304
+ # # │ 2020-01-01 00:00:00.999 ┆ 1000000 │
1305
+ # # │ 2020-01-01 00:00:01 ┆ 1000000 │
1306
+ # # └─────────────────────────┴──────────────────┘
1307
+ def total_nanoseconds
1308
+ Utils.wrap_expr(_rbexpr.dt_total_nanoseconds)
1309
+ end
1310
+ alias_method :nanoseconds, :total_nanoseconds
1311
+
1312
+ # Offset this date by a relative time offset.
1313
+ #
1314
+ # This differs from `Polars.col("foo") + timedelta` in that it can
1315
+ # take months and leap years into account. Note that only a single minus
1316
+ # sign is allowed in the `by` string, as the first character.
1317
+ #
1318
+ # @param by [String]
1319
+ # The offset is dictated by the following string language:
1320
+ #
1321
+ # - 1ns (1 nanosecond)
1322
+ # - 1us (1 microsecond)
1323
+ # - 1ms (1 millisecond)
1324
+ # - 1s (1 second)
1325
+ # - 1m (1 minute)
1326
+ # - 1h (1 hour)
1327
+ # - 1d (1 day)
1328
+ # - 1w (1 week)
1329
+ # - 1mo (1 calendar month)
1330
+ # - 1y (1 calendar year)
1331
+ # - 1i (1 index count)
1332
+ #
1333
+ # @return [Expr]
1334
+ #
1335
+ # @example
1336
+ # df = Polars::DataFrame.new(
1337
+ # {
1338
+ # "dates" => Polars.date_range(
1339
+ # DateTime.new(2000, 1, 1), DateTime.new(2005, 1, 1), "1y"
1340
+ # )
1341
+ # }
1342
+ # )
1343
+ # df.select(
1344
+ # [
1345
+ # Polars.col("dates").dt.offset_by("1y").alias("date_plus_1y"),
1346
+ # Polars.col("dates").dt.offset_by("-1y2mo").alias("date_min")
1347
+ # ]
1348
+ # )
1349
+ # # =>
1350
+ # # shape: (6, 2)
1351
+ # # ┌─────────────────────┬─────────────────────┐
1352
+ # # │ date_plus_1y ┆ date_min │
1353
+ # # │ --- ┆ --- │
1354
+ # # │ datetime[μs] ┆ datetime[μs] │
1355
+ # # ╞═════════════════════╪═════════════════════╡
1356
+ # # │ 2001-01-01 00:00:00 ┆ 1998-11-01 00:00:00 │
1357
+ # # │ 2002-01-01 00:00:00 ┆ 1999-11-01 00:00:00 │
1358
+ # # │ 2003-01-01 00:00:00 ┆ 2000-11-01 00:00:00 │
1359
+ # # │ 2004-01-01 00:00:00 ┆ 2001-11-01 00:00:00 │
1360
+ # # │ 2005-01-01 00:00:00 ┆ 2002-11-01 00:00:00 │
1361
+ # # │ 2006-01-01 00:00:00 ┆ 2003-11-01 00:00:00 │
1362
+ # # └─────────────────────┴─────────────────────┘
1363
+ def offset_by(by)
1364
+ by = Utils.parse_as_expression(by, str_as_lit: true)
1365
+ Utils.wrap_expr(_rbexpr.dt_offset_by(by))
1366
+ end
1367
+
1368
+ # Roll backward to the first day of the month.
1369
+ #
1370
+ # @return [Expr]
1371
+ #
1372
+ # @example
1373
+ # df = Polars::DataFrame.new(
1374
+ # {
1375
+ # "dates" => Polars.date_range(
1376
+ # DateTime.new(2000, 1, 15, 2),
1377
+ # DateTime.new(2000, 12, 15, 2),
1378
+ # "1mo"
1379
+ # )
1380
+ # }
1381
+ # )
1382
+ # df.select(Polars.col("dates").dt.month_start)
1383
+ # # =>
1384
+ # # shape: (12, 1)
1385
+ # # ┌─────────────────────┐
1386
+ # # │ dates │
1387
+ # # │ --- │
1388
+ # # │ datetime[μs] │
1389
+ # # ╞═════════════════════╡
1390
+ # # │ 2000-01-01 02:00:00 │
1391
+ # # │ 2000-02-01 02:00:00 │
1392
+ # # │ 2000-03-01 02:00:00 │
1393
+ # # │ 2000-04-01 02:00:00 │
1394
+ # # │ 2000-05-01 02:00:00 │
1395
+ # # │ … │
1396
+ # # │ 2000-08-01 02:00:00 │
1397
+ # # │ 2000-09-01 02:00:00 │
1398
+ # # │ 2000-10-01 02:00:00 │
1399
+ # # │ 2000-11-01 02:00:00 │
1400
+ # # │ 2000-12-01 02:00:00 │
1401
+ # # └─────────────────────┘
1402
+ def month_start
1403
+ Utils.wrap_expr(_rbexpr.dt_month_start)
1404
+ end
1405
+
1406
+ # Roll forward to the last day of the month.
1407
+ #
1408
+ # @return [Expr]
1409
+ #
1410
+ # @example
1411
+ # df = Polars::DataFrame.new(
1412
+ # {
1413
+ # "dates" => Polars.date_range(
1414
+ # DateTime.new(2000, 1, 15, 2),
1415
+ # DateTime.new(2000, 12, 15, 2),
1416
+ # "1mo"
1417
+ # )
1418
+ # }
1419
+ # )
1420
+ # df.select(Polars.col("dates").dt.month_end)
1421
+ # # =>
1422
+ # # shape: (12, 1)
1423
+ # # ┌─────────────────────┐
1424
+ # # │ dates │
1425
+ # # │ --- │
1426
+ # # │ datetime[μs] │
1427
+ # # ╞═════════════════════╡
1428
+ # # │ 2000-01-31 02:00:00 │
1429
+ # # │ 2000-02-29 02:00:00 │
1430
+ # # │ 2000-03-31 02:00:00 │
1431
+ # # │ 2000-04-30 02:00:00 │
1432
+ # # │ 2000-05-31 02:00:00 │
1433
+ # # │ … │
1434
+ # # │ 2000-08-31 02:00:00 │
1435
+ # # │ 2000-09-30 02:00:00 │
1436
+ # # │ 2000-10-31 02:00:00 │
1437
+ # # │ 2000-11-30 02:00:00 │
1438
+ # # │ 2000-12-31 02:00:00 │
1439
+ # # └─────────────────────┘
1440
+ def month_end
1441
+ Utils.wrap_expr(_rbexpr.dt_month_end)
1442
+ end
1443
+ end
1444
+ end