]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add and document %(time:now)
authorAlan T. DeKok <aland@freeradius.org>
Thu, 19 Jan 2023 17:50:56 +0000 (12:50 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 19 Jan 2023 18:05:03 +0000 (13:05 -0500)
which returns a _boxed_ time, and not a stupid integer.

doc/antora/modules/reference/pages/xlat/builtin.adoc
doc/antora/modules/reference/pages/xlat/character.adoc
src/lib/unlang/xlat_builtin.c

index 0c7c6593d6281e54eb701ae928caadab3ba34db0..a48786dceed4fd092f59da5f51fb5c6279390b83 100644 (file)
@@ -1131,5 +1131,29 @@ update reply {
 Caipirinha,is,a,light,and,refreshing,drink!
 ```
 
-// Copyright (C) 2021 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
+### %(time:)
+
+Return the current time.
+
+.Return: _date_.
+
+If no argument is passed, it returns the current time.  Otherwise if the argument is:
+
+* `now` - returns the current time
+* `request` - returns the time at which the request packet was received (always less than `now`!)
+* any other string is parsed as type `date`, using the normal date parsing routines.
+
+[NOTE]
+====
+This expansion should be used in preference to the xref:xlat/character.adoc[single letter expansions] `%l`.  That expansion returns integer seconds, and is not suitable for millisecond or microsecond resolution.
+====
+
+.Example
+
+[source,unlang]
+----
+&Acct-Start-Time := %(time:now)
+----
+
+// Copyright (C) 2023 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
 // Development of this documentation was sponsored by Network RADIUS SAS.
index 48185eef1fda92446ac11b9e58ef74796d7846c5..c8488609fe5c278005db25849fdfcaf37ccf93d1 100644 (file)
@@ -1,28 +1,47 @@
 = Single Letter Expansions
 
 The following are single letter expansions.  These expansions do not
-use the typical `%{...}` format.  Instead, they are short-cuts for
-simple, common cases.
+use the typical `%{...}` format.
+
+[NOTE]
+====
+In general, these expansions _should not be used_.
+====
+
+The xref:xlat/builtin.adoc[builtin] `%(time:...)` expansion and the
+xref:raddb:mods-available/date.adoc[date] module should be used
+instead of these expansions.
+
 
 == Current Time
 
 `%c`::
 
 The current Unix epoch time in seconds. This is an unsigned decimal number.
-It should be used with time-based calculations.
 
 `%C`::
 
 The microsecond component of the current epoch time. This is an unsigned
-decimal number. It should be used with time-based calculations.
+decimal number.
 
+Note that creating a "fractional" time from an expansion like `%c.%C`
+should only be used when creating strings, such as for logging.  If
+you need to calculate time differences, the time values should be left
+as type `date`, and then you can substract two dates to get a
+`time_delta`.  That `time_delta` can then be printed in an appropriate
+precision and scale.
 
 == Request Time
 
 `%l`::
 
-The Unix timestamp of when the request was received. This is an unsigned
-decimal number. It should be used with time-based calculations.
+The Unix timestamp of when the request was received. This is an
+unsigned decimal number, and returns an integer number of seconds
+since the Unix epoch.
+
+This expansion is only useful where the time resolution is in seconds.
+If more resolution is needed, the xref:xlat/builtin.adoc[builtin]
+`%(time:...)` expansion should be used instead.
 
 `%Y`::
 
@@ -60,14 +79,22 @@ Request date in the format `YYYYMMDD`.
 
 Request timestamp in SQL format, `YYYY-mmm-ddd HH:MM:SS`.
 
+The xref:raddb:mods-available/date.adoc[date] module should be used
+instead.
+
 `%t`::
 
 Request timestamp in _ctime_ format, `Www Mmm dd HH:MM:SS YYYY`.
 
+The xref:raddb:mods-available/date.adoc[date] module should be used
+instead.
+
 `%T`::
 
 Request timestamp in ISO format, `YYYY-mm-ddTHH:MM:SS.000`.
 
+The xref:raddb:mods-available/date.adoc[date] module should be used
+instead.
 
-// Copyright (C) 2021 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
+// Copyright (C) 2023 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
 // Development of this documentation was sponsored by Network RADIUS SAS.
index a79a87639daa5322b4e5cb4da0ea5b305e9c60e9..226cda34480ecc4978bee62a29c7ef4dcd902a36 100644 (file)
@@ -3476,6 +3476,53 @@ static xlat_action_t xlat_func_subst(TALLOC_CTX *ctx, fr_dcursor_t *out,
 }
 
 
+static xlat_arg_parser_t const xlat_func_time_args[] = {
+       { .required = false, .single = true, .type = FR_TYPE_STRING },
+       XLAT_ARG_PARSER_TERMINATOR
+};
+
+/** Return the time as a #FR_TYPE_DATE
+ *
+@verbatim
+%(time:)
+@endverbatim
+ *
+ * Example:
+@verbatim
+update reply {
+       &Reply-Message := "%{expr:%{time:now} - %{time:request}}
+}
+@endverbatim
+ *
+ * @ingroup xlat_functions
+ */
+static xlat_action_t xlat_func_time(TALLOC_CTX *ctx, fr_dcursor_t *out,
+                                   UNUSED xlat_ctx_t const *xctx,
+                                   request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in)
+{
+       fr_value_box_t          *arg = fr_value_box_list_head(in);
+       fr_value_box_t          *vb;
+       fr_unix_time_t          value;
+
+       if (!arg || (strcmp(arg->vb_strvalue, "now") == 0)) {
+               value = fr_time_to_unix_time(fr_time());
+
+       } else if (strcmp(arg->vb_strvalue, "request") == 0) {
+               value = fr_time_to_unix_time(request->packet->timestamp);
+
+       } else if (fr_unix_time_from_str(&value, arg->vb_strvalue, FR_TIME_RES_SEC) < 0) {
+               REDEBUG("Invalid time specification '%s'", arg->vb_strvalue);
+               return XLAT_ACTION_FAIL;
+       }
+
+       MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_DATE, NULL, false));
+       vb->vb_date = value;
+       fr_dcursor_append(out, vb);
+
+       return XLAT_ACTION_DONE;
+}
+
+
 /** Change case of a string
  *
  * If upper is true, change to uppercase, otherwise, change to lowercase
@@ -4010,6 +4057,7 @@ do { \
        XLAT_REGISTER_ARGS("nexttime", xlat_func_next_time, FR_TYPE_UINT64, xlat_func_next_time_args);
        XLAT_REGISTER_ARGS("pairs", xlat_func_pairs, FR_TYPE_STRING, xlat_func_pairs_args);
        XLAT_REGISTER_ARGS("subst", xlat_func_subst, FR_TYPE_STRING, xlat_func_subst_args);
+       XLAT_REGISTER_ARGS("time", xlat_func_time, FR_TYPE_DATE, xlat_func_time_args);
        XLAT_REGISTER_ARGS("trigger", trigger_xlat, FR_TYPE_STRING, trigger_xlat_args);
 
        /*