polars-df 0.13.0-x64-mingw-ucrt

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