/proc/self/cwd/runtime/standard/time_functions.cc
Line | Count | Source |
1 | | // Copyright 2023 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include "runtime/standard/time_functions.h" |
16 | | |
17 | | #include <cstdint> |
18 | | #include <functional> |
19 | | #include <string> |
20 | | |
21 | | #include "absl/status/status.h" |
22 | | #include "absl/status/statusor.h" |
23 | | #include "absl/strings/match.h" |
24 | | #include "absl/strings/str_replace.h" |
25 | | #include "absl/strings/string_view.h" |
26 | | #include "absl/time/civil_time.h" |
27 | | #include "absl/time/time.h" |
28 | | #include "base/builtins.h" |
29 | | #include "base/function_adapter.h" |
30 | | #include "common/value.h" |
31 | | #include "internal/overflow.h" |
32 | | #include "internal/status_macros.h" |
33 | | #include "runtime/function_registry.h" |
34 | | #include "runtime/runtime_options.h" |
35 | | |
36 | | namespace cel { |
37 | | namespace { |
38 | | |
39 | | // Timestamp |
40 | | absl::Status FindTimeBreakdown(absl::Time timestamp, absl::string_view tz, |
41 | 0 | absl::TimeZone::CivilInfo* breakdown) { |
42 | 0 | absl::TimeZone time_zone; |
43 | | |
44 | | // Early return if there is no timezone. |
45 | 0 | if (tz.empty()) { |
46 | 0 | *breakdown = time_zone.At(timestamp); |
47 | 0 | return absl::OkStatus(); |
48 | 0 | } |
49 | | |
50 | | // Check to see whether the timezone is an IANA timezone. |
51 | 0 | if (absl::LoadTimeZone(tz, &time_zone)) { |
52 | 0 | *breakdown = time_zone.At(timestamp); |
53 | 0 | return absl::OkStatus(); |
54 | 0 | } |
55 | | |
56 | | // Check for times of the format: [+-]HH:MM and convert them into durations |
57 | | // specified as [+-]HHhMMm. |
58 | 0 | if (absl::StrContains(tz, ":")) { |
59 | 0 | std::string dur = absl::StrCat(tz, "m"); |
60 | 0 | absl::StrReplaceAll({{":", "h"}}, &dur); |
61 | 0 | absl::Duration d; |
62 | 0 | if (absl::ParseDuration(dur, &d)) { |
63 | 0 | timestamp += d; |
64 | 0 | *breakdown = time_zone.At(timestamp); |
65 | 0 | return absl::OkStatus(); |
66 | 0 | } |
67 | 0 | } |
68 | | |
69 | | // Otherwise, error. |
70 | 0 | return absl::InvalidArgumentError("Invalid timezone"); |
71 | 0 | } |
72 | | |
73 | | Value GetTimeBreakdownPart( |
74 | | absl::Time timestamp, absl::string_view tz, |
75 | | const std::function<int64_t(const absl::TimeZone::CivilInfo&)>& |
76 | 0 | extractor_func) { |
77 | 0 | absl::TimeZone::CivilInfo breakdown; |
78 | 0 | auto status = FindTimeBreakdown(timestamp, tz, &breakdown); |
79 | |
|
80 | 0 | if (!status.ok()) { |
81 | 0 | return ErrorValue(status); |
82 | 0 | } |
83 | | |
84 | 0 | return IntValue(extractor_func(breakdown)); |
85 | 0 | } |
86 | | |
87 | 0 | Value GetFullYear(absl::Time timestamp, absl::string_view tz) { |
88 | 0 | return GetTimeBreakdownPart(timestamp, tz, |
89 | 0 | [](const absl::TimeZone::CivilInfo& breakdown) { |
90 | 0 | return breakdown.cs.year(); |
91 | 0 | }); |
92 | 0 | } |
93 | | |
94 | 0 | Value GetMonth(absl::Time timestamp, absl::string_view tz) { |
95 | 0 | return GetTimeBreakdownPart(timestamp, tz, |
96 | 0 | [](const absl::TimeZone::CivilInfo& breakdown) { |
97 | 0 | return breakdown.cs.month() - 1; |
98 | 0 | }); |
99 | 0 | } |
100 | | |
101 | 0 | Value GetDayOfYear(absl::Time timestamp, absl::string_view tz) { |
102 | 0 | return GetTimeBreakdownPart( |
103 | 0 | timestamp, tz, [](const absl::TimeZone::CivilInfo& breakdown) { |
104 | 0 | return absl::GetYearDay(absl::CivilDay(breakdown.cs)) - 1; |
105 | 0 | }); |
106 | 0 | } |
107 | | |
108 | 0 | Value GetDayOfMonth(absl::Time timestamp, absl::string_view tz) { |
109 | 0 | return GetTimeBreakdownPart(timestamp, tz, |
110 | 0 | [](const absl::TimeZone::CivilInfo& breakdown) { |
111 | 0 | return breakdown.cs.day() - 1; |
112 | 0 | }); |
113 | 0 | } |
114 | | |
115 | 0 | Value GetDate(absl::Time timestamp, absl::string_view tz) { |
116 | 0 | return GetTimeBreakdownPart(timestamp, tz, |
117 | 0 | [](const absl::TimeZone::CivilInfo& breakdown) { |
118 | 0 | return breakdown.cs.day(); |
119 | 0 | }); |
120 | 0 | } |
121 | | |
122 | 0 | Value GetDayOfWeek(absl::Time timestamp, absl::string_view tz) { |
123 | 0 | return GetTimeBreakdownPart( |
124 | 0 | timestamp, tz, [](const absl::TimeZone::CivilInfo& breakdown) { |
125 | 0 | absl::Weekday weekday = absl::GetWeekday(breakdown.cs); |
126 | | |
127 | | // get day of week from the date in UTC, zero-based, zero for Sunday, |
128 | | // based on GetDayOfWeek CEL function definition. |
129 | 0 | int weekday_num = static_cast<int>(weekday); |
130 | 0 | weekday_num = (weekday_num == 6) ? 0 : weekday_num + 1; |
131 | 0 | return weekday_num; |
132 | 0 | }); |
133 | 0 | } |
134 | | |
135 | 0 | Value GetHours(absl::Time timestamp, absl::string_view tz) { |
136 | 0 | return GetTimeBreakdownPart(timestamp, tz, |
137 | 0 | [](const absl::TimeZone::CivilInfo& breakdown) { |
138 | 0 | return breakdown.cs.hour(); |
139 | 0 | }); |
140 | 0 | } |
141 | | |
142 | 0 | Value GetMinutes(absl::Time timestamp, absl::string_view tz) { |
143 | 0 | return GetTimeBreakdownPart(timestamp, tz, |
144 | 0 | [](const absl::TimeZone::CivilInfo& breakdown) { |
145 | 0 | return breakdown.cs.minute(); |
146 | 0 | }); |
147 | 0 | } |
148 | | |
149 | 0 | Value GetSeconds(absl::Time timestamp, absl::string_view tz) { |
150 | 0 | return GetTimeBreakdownPart(timestamp, tz, |
151 | 0 | [](const absl::TimeZone::CivilInfo& breakdown) { |
152 | 0 | return breakdown.cs.second(); |
153 | 0 | }); |
154 | 0 | } |
155 | | |
156 | 0 | Value GetMilliseconds(absl::Time timestamp, absl::string_view tz) { |
157 | 0 | return GetTimeBreakdownPart( |
158 | 0 | timestamp, tz, [](const absl::TimeZone::CivilInfo& breakdown) { |
159 | 0 | return absl::ToInt64Milliseconds(breakdown.subsecond); |
160 | 0 | }); |
161 | 0 | } |
162 | | |
163 | | absl::Status RegisterTimestampFunctions(FunctionRegistry& registry, |
164 | 14.5k | const RuntimeOptions& options) { |
165 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
166 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
167 | 14.5k | CreateDescriptor(builtin::kFullYear, true), |
168 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
169 | 14.5k | WrapFunction([](absl::Time ts, const StringValue& tz) -> Value { |
170 | 14.5k | return GetFullYear(ts, tz.ToString()); |
171 | 14.5k | }))); |
172 | | |
173 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
174 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::CreateDescriptor( |
175 | 14.5k | builtin::kFullYear, true), |
176 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::WrapFunction( |
177 | 14.5k | [](absl::Time ts) -> Value { return GetFullYear(ts, ""); }))); |
178 | | |
179 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
180 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
181 | 14.5k | CreateDescriptor(builtin::kMonth, true), |
182 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
183 | 14.5k | WrapFunction([](absl::Time ts, const StringValue& tz) -> Value { |
184 | 14.5k | return GetMonth(ts, tz.ToString()); |
185 | 14.5k | }))); |
186 | | |
187 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
188 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::CreateDescriptor(builtin::kMonth, |
189 | 14.5k | true), |
190 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::WrapFunction( |
191 | 14.5k | [](absl::Time ts) -> Value { return GetMonth(ts, ""); }))); |
192 | | |
193 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
194 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
195 | 14.5k | CreateDescriptor(builtin::kDayOfYear, true), |
196 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
197 | 14.5k | WrapFunction([](absl::Time ts, const StringValue& tz) -> Value { |
198 | 14.5k | return GetDayOfYear(ts, tz.ToString()); |
199 | 14.5k | }))); |
200 | | |
201 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
202 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::CreateDescriptor( |
203 | 14.5k | builtin::kDayOfYear, true), |
204 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::WrapFunction( |
205 | 14.5k | [](absl::Time ts) -> Value { return GetDayOfYear(ts, ""); }))); |
206 | | |
207 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
208 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
209 | 14.5k | CreateDescriptor(builtin::kDayOfMonth, true), |
210 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
211 | 14.5k | WrapFunction([](absl::Time ts, const StringValue& tz) -> Value { |
212 | 14.5k | return GetDayOfMonth(ts, tz.ToString()); |
213 | 14.5k | }))); |
214 | | |
215 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
216 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::CreateDescriptor( |
217 | 14.5k | builtin::kDayOfMonth, true), |
218 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::WrapFunction( |
219 | 14.5k | [](absl::Time ts) -> Value { return GetDayOfMonth(ts, ""); }))); |
220 | | |
221 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
222 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
223 | 14.5k | CreateDescriptor(builtin::kDate, true), |
224 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
225 | 14.5k | WrapFunction([](absl::Time ts, const StringValue& tz) -> Value { |
226 | 14.5k | return GetDate(ts, tz.ToString()); |
227 | 14.5k | }))); |
228 | | |
229 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
230 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::CreateDescriptor(builtin::kDate, |
231 | 14.5k | true), |
232 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::WrapFunction( |
233 | 14.5k | [](absl::Time ts) -> Value { return GetDate(ts, ""); }))); |
234 | | |
235 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
236 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
237 | 14.5k | CreateDescriptor(builtin::kDayOfWeek, true), |
238 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
239 | 14.5k | WrapFunction([](absl::Time ts, const StringValue& tz) -> Value { |
240 | 14.5k | return GetDayOfWeek(ts, tz.ToString()); |
241 | 14.5k | }))); |
242 | | |
243 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
244 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::CreateDescriptor( |
245 | 14.5k | builtin::kDayOfWeek, true), |
246 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::WrapFunction( |
247 | 14.5k | [](absl::Time ts) -> Value { return GetDayOfWeek(ts, ""); }))); |
248 | | |
249 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
250 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
251 | 14.5k | CreateDescriptor(builtin::kHours, true), |
252 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
253 | 14.5k | WrapFunction([](absl::Time ts, const StringValue& tz) -> Value { |
254 | 14.5k | return GetHours(ts, tz.ToString()); |
255 | 14.5k | }))); |
256 | | |
257 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
258 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::CreateDescriptor(builtin::kHours, |
259 | 14.5k | true), |
260 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::WrapFunction( |
261 | 14.5k | [](absl::Time ts) -> Value { return GetHours(ts, ""); }))); |
262 | | |
263 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
264 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
265 | 14.5k | CreateDescriptor(builtin::kMinutes, true), |
266 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
267 | 14.5k | WrapFunction([](absl::Time ts, const StringValue& tz) -> Value { |
268 | 14.5k | return GetMinutes(ts, tz.ToString()); |
269 | 14.5k | }))); |
270 | | |
271 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
272 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::CreateDescriptor( |
273 | 14.5k | builtin::kMinutes, true), |
274 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::WrapFunction( |
275 | 14.5k | [](absl::Time ts) -> Value { return GetMinutes(ts, ""); }))); |
276 | | |
277 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
278 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
279 | 14.5k | CreateDescriptor(builtin::kSeconds, true), |
280 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
281 | 14.5k | WrapFunction([](absl::Time ts, const StringValue& tz) -> Value { |
282 | 14.5k | return GetSeconds(ts, tz.ToString()); |
283 | 14.5k | }))); |
284 | | |
285 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
286 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::CreateDescriptor( |
287 | 14.5k | builtin::kSeconds, true), |
288 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::WrapFunction( |
289 | 14.5k | [](absl::Time ts) -> Value { return GetSeconds(ts, ""); }))); |
290 | | |
291 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
292 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
293 | 14.5k | CreateDescriptor(builtin::kMilliseconds, true), |
294 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, const StringValue&>:: |
295 | 14.5k | WrapFunction([](absl::Time ts, const StringValue& tz) -> Value { |
296 | 14.5k | return GetMilliseconds(ts, tz.ToString()); |
297 | 14.5k | }))); |
298 | | |
299 | 14.5k | return registry.Register( |
300 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::CreateDescriptor( |
301 | 14.5k | builtin::kMilliseconds, true), |
302 | 14.5k | UnaryFunctionAdapter<Value, absl::Time>::WrapFunction( |
303 | 14.5k | [](absl::Time ts) -> Value { return GetMilliseconds(ts, ""); })); |
304 | 14.5k | } |
305 | | |
306 | | absl::Status RegisterCheckedTimeArithmeticFunctions( |
307 | 0 | FunctionRegistry& registry) { |
308 | 0 | CEL_RETURN_IF_ERROR(registry.Register( |
309 | 0 | BinaryFunctionAdapter<Value, absl::Time, |
310 | 0 | absl::Duration>::CreateDescriptor(builtin::kAdd, |
311 | 0 | false), |
312 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, absl::Time, absl::Duration>:: |
313 | 0 | WrapFunction( |
314 | 0 | [](absl::Time t1, absl::Duration d2) -> absl::StatusOr<Value> { |
315 | 0 | auto sum = cel::internal::CheckedAdd(t1, d2); |
316 | 0 | if (!sum.ok()) { |
317 | 0 | return ErrorValue(sum.status()); |
318 | 0 | } |
319 | 0 | return TimestampValue(*sum); |
320 | 0 | }))); |
321 | | |
322 | 0 | CEL_RETURN_IF_ERROR(registry.Register( |
323 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, absl::Duration, |
324 | 0 | absl::Time>::CreateDescriptor(builtin::kAdd, false), |
325 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, absl::Duration, absl::Time>:: |
326 | 0 | WrapFunction( |
327 | 0 | [](absl::Duration d2, absl::Time t1) -> absl::StatusOr<Value> { |
328 | 0 | auto sum = cel::internal::CheckedAdd(t1, d2); |
329 | 0 | if (!sum.ok()) { |
330 | 0 | return ErrorValue(sum.status()); |
331 | 0 | } |
332 | 0 | return TimestampValue(*sum); |
333 | 0 | }))); |
334 | | |
335 | 0 | CEL_RETURN_IF_ERROR(registry.Register( |
336 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, absl::Duration, |
337 | 0 | absl::Duration>::CreateDescriptor(builtin::kAdd, |
338 | 0 | false), |
339 | 0 | BinaryFunctionAdapter< |
340 | 0 | absl::StatusOr<Value>, absl::Duration, |
341 | 0 | absl::Duration>::WrapFunction([](absl::Duration d1, absl::Duration d2) |
342 | 0 | -> absl::StatusOr<Value> { |
343 | 0 | auto sum = cel::internal::CheckedAdd(d1, d2); |
344 | 0 | if (!sum.ok()) { |
345 | 0 | return ErrorValue(sum.status()); |
346 | 0 | } |
347 | 0 | return DurationValue(*sum); |
348 | 0 | }))); |
349 | | |
350 | 0 | CEL_RETURN_IF_ERROR(registry.Register( |
351 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, absl::Time, absl::Duration>:: |
352 | 0 | CreateDescriptor(builtin::kSubtract, false), |
353 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, absl::Time, absl::Duration>:: |
354 | 0 | WrapFunction( |
355 | 0 | [](absl::Time t1, absl::Duration d2) -> absl::StatusOr<Value> { |
356 | 0 | auto diff = cel::internal::CheckedSub(t1, d2); |
357 | 0 | if (!diff.ok()) { |
358 | 0 | return ErrorValue(diff.status()); |
359 | 0 | } |
360 | 0 | return TimestampValue(*diff); |
361 | 0 | }))); |
362 | | |
363 | 0 | CEL_RETURN_IF_ERROR(registry.Register( |
364 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, absl::Time, |
365 | 0 | absl::Time>::CreateDescriptor(builtin::kSubtract, |
366 | 0 | false), |
367 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, absl::Time, absl::Time>:: |
368 | 0 | WrapFunction( |
369 | 0 | [](absl::Time t1, absl::Time t2) -> absl::StatusOr<Value> { |
370 | 0 | auto diff = cel::internal::CheckedSub(t1, t2); |
371 | 0 | if (!diff.ok()) { |
372 | 0 | return ErrorValue(diff.status()); |
373 | 0 | } |
374 | 0 | return DurationValue(*diff); |
375 | 0 | }))); |
376 | | |
377 | 0 | CEL_RETURN_IF_ERROR(registry.Register( |
378 | 0 | BinaryFunctionAdapter< |
379 | 0 | absl::StatusOr<Value>, absl::Duration, |
380 | 0 | absl::Duration>::CreateDescriptor(builtin::kSubtract, false), |
381 | 0 | BinaryFunctionAdapter< |
382 | 0 | absl::StatusOr<Value>, absl::Duration, |
383 | 0 | absl::Duration>::WrapFunction([](absl::Duration d1, absl::Duration d2) |
384 | 0 | -> absl::StatusOr<Value> { |
385 | 0 | auto diff = cel::internal::CheckedSub(d1, d2); |
386 | 0 | if (!diff.ok()) { |
387 | 0 | return ErrorValue(diff.status()); |
388 | 0 | } |
389 | 0 | return DurationValue(*diff); |
390 | 0 | }))); |
391 | | |
392 | 0 | return absl::OkStatus(); |
393 | 0 | } |
394 | | |
395 | | absl::Status RegisterUncheckedTimeArithmeticFunctions( |
396 | 14.5k | FunctionRegistry& registry) { |
397 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
398 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, |
399 | 14.5k | absl::Duration>::CreateDescriptor(builtin::kAdd, |
400 | 14.5k | false), |
401 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, absl::Duration>::WrapFunction( |
402 | 14.5k | [](absl::Time t1, absl::Duration d2) -> Value { |
403 | 14.5k | return UnsafeTimestampValue(t1 + d2); |
404 | 14.5k | }))); |
405 | | |
406 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
407 | 14.5k | BinaryFunctionAdapter<Value, absl::Duration, |
408 | 14.5k | absl::Time>::CreateDescriptor(builtin::kAdd, false), |
409 | 14.5k | BinaryFunctionAdapter<Value, absl::Duration, absl::Time>::WrapFunction( |
410 | 14.5k | [](absl::Duration d2, absl::Time t1) -> Value { |
411 | 14.5k | return UnsafeTimestampValue(t1 + d2); |
412 | 14.5k | }))); |
413 | | |
414 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
415 | 14.5k | BinaryFunctionAdapter<Value, absl::Duration, |
416 | 14.5k | absl::Duration>::CreateDescriptor(builtin::kAdd, |
417 | 14.5k | false), |
418 | 14.5k | BinaryFunctionAdapter<Value, absl::Duration, absl::Duration>:: |
419 | 14.5k | WrapFunction([](absl::Duration d1, absl::Duration d2) -> Value { |
420 | 14.5k | return UnsafeDurationValue(d1 + d2); |
421 | 14.5k | }))); |
422 | | |
423 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
424 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, absl::Duration>:: |
425 | 14.5k | CreateDescriptor(builtin::kSubtract, false), |
426 | | |
427 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, absl::Duration>::WrapFunction( |
428 | | |
429 | 14.5k | [](absl::Time t1, absl::Duration d2) -> Value { |
430 | 14.5k | return UnsafeTimestampValue(t1 - d2); |
431 | 14.5k | }))); |
432 | | |
433 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
434 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, absl::Time>::CreateDescriptor( |
435 | 14.5k | builtin::kSubtract, false), |
436 | 14.5k | BinaryFunctionAdapter<Value, absl::Time, absl::Time>::WrapFunction( |
437 | | |
438 | 14.5k | [](absl::Time t1, absl::Time t2) -> Value { |
439 | 14.5k | return UnsafeDurationValue(t1 - t2); |
440 | 14.5k | }))); |
441 | | |
442 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
443 | 14.5k | BinaryFunctionAdapter<Value, absl::Duration, absl::Duration>:: |
444 | 14.5k | CreateDescriptor(builtin::kSubtract, false), |
445 | 14.5k | BinaryFunctionAdapter<Value, absl::Duration, absl::Duration>:: |
446 | 14.5k | WrapFunction([](absl::Duration d1, absl::Duration d2) -> Value { |
447 | 14.5k | return UnsafeDurationValue(d1 - d2); |
448 | 14.5k | }))); |
449 | | |
450 | 14.5k | return absl::OkStatus(); |
451 | 14.5k | } |
452 | | |
453 | 14.5k | absl::Status RegisterDurationFunctions(FunctionRegistry& registry) { |
454 | | // duration breakdown accessor functions |
455 | 14.5k | using DurationAccessorFunction = |
456 | 14.5k | UnaryFunctionAdapter<int64_t, absl::Duration>; |
457 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
458 | 14.5k | DurationAccessorFunction::CreateDescriptor(builtin::kHours, true), |
459 | 14.5k | DurationAccessorFunction::WrapFunction( |
460 | 14.5k | [](absl::Duration d) -> int64_t { return absl::ToInt64Hours(d); }))); |
461 | | |
462 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
463 | 14.5k | DurationAccessorFunction::CreateDescriptor(builtin::kMinutes, true), |
464 | 14.5k | DurationAccessorFunction::WrapFunction([](absl::Duration d) -> int64_t { |
465 | 14.5k | return absl::ToInt64Minutes(d); |
466 | 14.5k | }))); |
467 | | |
468 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
469 | 14.5k | DurationAccessorFunction::CreateDescriptor(builtin::kSeconds, true), |
470 | 14.5k | DurationAccessorFunction::WrapFunction([](absl::Duration d) -> int64_t { |
471 | 14.5k | return absl::ToInt64Seconds(d); |
472 | 14.5k | }))); |
473 | | |
474 | 14.5k | return registry.Register( |
475 | 14.5k | DurationAccessorFunction::CreateDescriptor(builtin::kMilliseconds, true), |
476 | 14.5k | DurationAccessorFunction::WrapFunction([](absl::Duration d) -> int64_t { |
477 | 0 | constexpr int64_t millis_per_second = 1000L; |
478 | 0 | return absl::ToInt64Milliseconds(d) % millis_per_second; |
479 | 0 | })); |
480 | 14.5k | } |
481 | | |
482 | | } // namespace |
483 | | |
484 | | absl::Status RegisterTimeFunctions(FunctionRegistry& registry, |
485 | 14.5k | const RuntimeOptions& options) { |
486 | 14.5k | CEL_RETURN_IF_ERROR(RegisterTimestampFunctions(registry, options)); |
487 | 14.5k | CEL_RETURN_IF_ERROR(RegisterDurationFunctions(registry)); |
488 | | |
489 | | // Special arithmetic operators for Timestamp and Duration |
490 | | // TODO(uncreated-issue/37): deprecate unchecked time math functions when clients no |
491 | | // longer depend on them. |
492 | 14.5k | if (options.enable_timestamp_duration_overflow_errors) { |
493 | 0 | return RegisterCheckedTimeArithmeticFunctions(registry); |
494 | 0 | } |
495 | | |
496 | 14.5k | return RegisterUncheckedTimeArithmeticFunctions(registry); |
497 | 14.5k | } |
498 | | |
499 | | } // namespace cel |