polars-df 0.13.0-x64-mingw-ucrt

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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