diff --git a/doc/content/xapi/storage/sxm.md b/doc/content/xapi/storage/sxm.md
index 8429f87321c..ee3b90276cc 100644
--- a/doc/content/xapi/storage/sxm.md
+++ b/doc/content/xapi/storage/sxm.md
@@ -450,8 +450,8 @@ but we've still got a bit of thinking to do: we sort the VDIs to copy based on a
let compare_fun v1 v2 =
let r = Int64.compare v1.size v2.size in
if r = 0 then
- let t1 = Date.to_float (Db.VDI.get_snapshot_time ~__context ~self:v1.vdi) in
- let t2 = Date.to_float (Db.VDI.get_snapshot_time ~__context ~self:v2.vdi) in
+ let t1 = Date.to_unix_time (Db.VDI.get_snapshot_time ~__context ~self:v1.vdi) in
+ let t2 = Date.to_unix_time (Db.VDI.get_snapshot_time ~__context ~self:v2.vdi) in
compare t1 t2
else r in
let all_vdis = all_vdis |> List.sort compare_fun in
diff --git a/ocaml/alerts/expiry_alert.ml b/ocaml/alerts/expiry_alert.ml
index 1ea19844ba6..d2667ff35df 100644
--- a/ocaml/alerts/expiry_alert.ml
+++ b/ocaml/alerts/expiry_alert.ml
@@ -50,7 +50,7 @@ let all_messages rpc session_id =
let message_body msg expiry =
Printf.sprintf "
%s%s" msg
- (Date.to_string expiry)
+ (Date.to_rfc3339 expiry)
let expired_message obj = Printf.sprintf "%s has expired." obj
@@ -58,7 +58,7 @@ let expiring_message obj = Printf.sprintf "%s is expiring soon." obj
let maybe_generate_alert now obj_description alert_conditions expiry =
let remaining_days =
- days_until_expiry (Date.to_float now) (Date.to_float expiry)
+ days_until_expiry (Date.to_unix_time now) (Date.to_unix_time expiry)
in
alert_conditions
|> List.sort (fun (a, _) (b, _) -> compare a b)
diff --git a/ocaml/idl/datamodel.ml b/ocaml/idl/datamodel.ml
index 2efca2c2ce8..737ecc53b0f 100644
--- a/ocaml/idl/datamodel.ml
+++ b/ocaml/idl/datamodel.ml
@@ -217,9 +217,8 @@ module Session = struct
session instance has is_local_superuser set, then the value of \
this field is undefined."
; field ~in_product_since:rel_george ~qualifier:DynamicRO
- ~default_value:(Some (VDateTime (Date.of_float 0.)))
- ~ty:DateTime "validation_time"
- "time when session was last validated"
+ ~default_value:(Some (VDateTime Date.epoch)) ~ty:DateTime
+ "validation_time" "time when session was last validated"
; field ~in_product_since:rel_george ~qualifier:DynamicRO
~default_value:(Some (VString "")) ~ty:String "auth_user_sid"
"the subject identifier of the user that was externally \
@@ -3895,9 +3894,11 @@ module VDI = struct
; {
param_type= DateTime
; param_name= "snapshot_time"
- ; param_doc= "Storage-specific config"
+ ; param_doc=
+ "Storage-specific config. When the timezone is missing, UTC is \
+ assumed"
; param_release= tampa_release
- ; param_default= Some (VDateTime Date.never)
+ ; param_default= Some (VDateTime Date.epoch)
}
; {
param_type= Ref _vdi
@@ -4089,7 +4090,11 @@ module VDI = struct
~params:
[
(Ref _vdi, "self", "The VDI to modify")
- ; (DateTime, "value", "The snapshot time of this VDI.")
+ ; ( DateTime
+ , "value"
+ , "The snapshot time of this VDI. When the timezone is missing, UTC \
+ is assumed"
+ )
]
~flags:[`Session] ~doc:"Sets the snapshot time of this VDI."
~hide_from_docs:true ~allowed_roles:_R_LOCAL_ROOT_ONLY ()
@@ -4468,7 +4473,7 @@ module VDI = struct
~ty:(Set (Ref _vdi)) ~doc_tags:[Snapshots] "snapshots"
"List pointing to all the VDIs snapshots."
; field ~in_product_since:rel_orlando
- ~default_value:(Some (VDateTime Date.never)) ~qualifier:DynamicRO
+ ~default_value:(Some (VDateTime Date.epoch)) ~qualifier:DynamicRO
~ty:DateTime ~doc_tags:[Snapshots] "snapshot_time"
"Date/time when this snapshot was created."
; field ~writer_roles:_R_VM_OP ~in_product_since:rel_orlando
@@ -4752,7 +4757,7 @@ module VBD_metrics = struct
uid _vbd_metrics
; namespace ~name:"io" ~contents:iobandwidth ()
; field ~qualifier:DynamicRO ~ty:DateTime
- ~default_value:(Some (VDateTime Date.never))
+ ~default_value:(Some (VDateTime Date.epoch))
~lifecycle:
[
(Published, rel_rio, "")
@@ -5511,7 +5516,11 @@ module VMPP = struct
~params:
[
(Ref _vmpp, "self", "The protection policy")
- ; (DateTime, "value", "the value to set")
+ ; ( DateTime
+ , "value"
+ , "When was the last backup was done. When the timezone is missing, \
+ UTC is assumed"
+ )
]
()
@@ -5521,7 +5530,11 @@ module VMPP = struct
~params:
[
(Ref _vmpp, "self", "The protection policy")
- ; (DateTime, "value", "the value to set")
+ ; ( DateTime
+ , "value"
+ , "When was the last archive was done. When the timezone is missing, \
+ UTC is assumed"
+ )
]
()
@@ -5669,7 +5682,7 @@ module VMPP = struct
"true if this protection policy's backup is running"
; field ~lifecycle:removed ~qualifier:DynamicRO ~ty:DateTime
"backup_last_run_time" "time of the last backup"
- ~default_value:(Some (VDateTime (Date.of_float 0.)))
+ ~default_value:(Some (VDateTime Date.epoch))
; field ~lifecycle:removed ~qualifier:StaticRO ~ty:archive_target_type
"archive_target_type" "type of the archive target config"
~default_value:(Some (VEnum "none"))
@@ -5693,7 +5706,7 @@ module VMPP = struct
"true if this protection policy's archive is running"
; field ~lifecycle:removed ~qualifier:DynamicRO ~ty:DateTime
"archive_last_run_time" "time of the last archive"
- ~default_value:(Some (VDateTime (Date.of_float 0.)))
+ ~default_value:(Some (VDateTime Date.epoch))
; field ~lifecycle:removed ~qualifier:DynamicRO ~ty:(Set (Ref _vm))
"VMs" "all VMs attached to this protection policy"
; field ~lifecycle:removed ~qualifier:StaticRO ~ty:Bool
@@ -5782,7 +5795,11 @@ module VMSS = struct
~params:
[
(Ref _vmss, "self", "The snapshot schedule")
- ; (DateTime, "value", "the value to set")
+ ; ( DateTime
+ , "value"
+ , "When was the schedule was last run. When a timezone is missing, \
+ UTC is assumed"
+ )
]
()
@@ -5856,7 +5873,7 @@ module VMSS = struct
~default_value:(Some (VMap []))
; field ~qualifier:DynamicRO ~ty:DateTime "last_run_time"
"time of the last snapshot"
- ~default_value:(Some (VDateTime (Date.of_float 0.)))
+ ~default_value:(Some (VDateTime Date.epoch))
; field ~qualifier:DynamicRO ~ty:(Set (Ref _vm)) "VMs"
"all VMs attached to this snapshot schedule"
]
@@ -6311,7 +6328,10 @@ module Message = struct
[
(cls, "cls", "The class of object")
; (String, "obj_uuid", "The uuid of the object")
- ; (DateTime, "since", "The cutoff time")
+ ; ( DateTime
+ , "since"
+ , "The cutoff time. When the timezone is missing, UTC is assumed"
+ )
]
~flags:[`Session]
~result:(Map (Ref _message, Record _message), "The relevant messages")
@@ -6319,7 +6339,13 @@ module Message = struct
let get_since =
call ~name:"get_since" ~in_product_since:rel_orlando
- ~params:[(DateTime, "since", "The cutoff time")]
+ ~params:
+ [
+ ( DateTime
+ , "since"
+ , "The cutoff time. When the timezone is missing, UTC is assumed"
+ )
+ ]
~flags:[`Session]
~result:(Map (Ref _message, Record _message), "The relevant messages")
~allowed_roles:_R_READ_ONLY ()
diff --git a/ocaml/idl/datamodel_certificate.ml b/ocaml/idl/datamodel_certificate.ml
index bfbdd2b60b5..53c594fb941 100644
--- a/ocaml/idl/datamodel_certificate.ml
+++ b/ocaml/idl/datamodel_certificate.ml
@@ -59,10 +59,10 @@ let t =
~default_value:(Some (VRef null_ref))
"The host where the certificate is installed"
; field ~qualifier:StaticRO ~lifecycle ~ty:DateTime "not_before"
- ~default_value:(Some (VDateTime Date.never))
+ ~default_value:(Some (VDateTime Date.epoch))
"Date after which the certificate is valid"
; field ~qualifier:StaticRO ~lifecycle ~ty:DateTime "not_after"
- ~default_value:(Some (VDateTime Date.never))
+ ~default_value:(Some (VDateTime Date.epoch))
"Date before which the certificate is valid"
; field ~qualifier:StaticRO
~lifecycle:
diff --git a/ocaml/idl/datamodel_host.ml b/ocaml/idl/datamodel_host.ml
index b7d34350819..d48470f3a71 100644
--- a/ocaml/idl/datamodel_host.ml
+++ b/ocaml/idl/datamodel_host.ml
@@ -935,7 +935,9 @@ let create_params =
; {
param_type= DateTime
; param_name= "last_software_update"
- ; param_doc= "Date and time when the last software update was applied."
+ ; param_doc=
+ "Date and time when the last software update was applied. When the \
+ timezone is missing, UTC is assumed"
; param_release= dundee_release
; param_default= Some (VDateTime Date.epoch)
}
@@ -2188,8 +2190,7 @@ let t =
"tls_verification_enabled" ~default_value:(Some (VBool false))
"True if this host has TLS verifcation enabled"
; field ~qualifier:DynamicRO ~lifecycle:[] ~ty:DateTime
- "last_software_update"
- ~default_value:(Some (VDateTime (Date.of_float 0.0)))
+ "last_software_update" ~default_value:(Some (VDateTime Date.epoch))
"Date and time when the last software update was applied"
; field ~qualifier:DynamicRO ~lifecycle:[] ~ty:Bool
~default_value:(Some (VBool false)) "https_only"
diff --git a/ocaml/idl/datamodel_types.ml b/ocaml/idl/datamodel_types.ml
index 61893c99e01..67a6fdd4ea1 100644
--- a/ocaml/idl/datamodel_types.ml
+++ b/ocaml/idl/datamodel_types.ml
@@ -26,12 +26,12 @@
*)
module Date = struct
- open Xapi_stdext_date
+ module Date = Xapi_stdext_date.Date
include Date
- let iso8601_of_rpc rpc = Date.of_string (Rpc.string_of_rpc rpc)
+ let t_of_rpc rpc = Date.of_iso8601 (Rpc.string_of_rpc rpc)
- let rpc_of_iso8601 date = Rpc.rpc_of_string (Date.to_string date)
+ let rpc_of_t date = Rpc.rpc_of_string (Date.to_rfc3339 date)
end
(* useful constants for product vsn tracking *)
@@ -418,7 +418,7 @@ type api_value =
| VInt of int64
| VFloat of float
| VBool of bool
- | VDateTime of Date.iso8601
+ | VDateTime of Date.t
| VEnum of string
| VMap of (api_value * api_value) list
| VSet of api_value list
diff --git a/ocaml/idl/datamodel_types.mli b/ocaml/idl/datamodel_types.mli
index 76ac814eb49..fbfb9e4a6f6 100644
--- a/ocaml/idl/datamodel_types.mli
+++ b/ocaml/idl/datamodel_types.mli
@@ -1,9 +1,9 @@
module Date : sig
include module type of Xapi_stdext_date.Date
- val iso8601_of_rpc : Rpc.t -> Xapi_stdext_date.Date.iso8601
+ val t_of_rpc : Rpc.t -> Xapi_stdext_date.Date.t
- val rpc_of_iso8601 : Xapi_stdext_date.Date.iso8601 -> Rpc.t
+ val rpc_of_t : Xapi_stdext_date.Date.t -> Rpc.t
end
val oss_since_303 : string option
@@ -115,7 +115,7 @@ type api_value =
| VInt of int64
| VFloat of float
| VBool of bool
- | VDateTime of Date.iso8601
+ | VDateTime of Date.t
| VEnum of string
| VMap of (api_value * api_value) list
| VSet of api_value list
diff --git a/ocaml/idl/datamodel_values.ml b/ocaml/idl/datamodel_values.ml
index 1b463d4b2e7..e270899b50f 100644
--- a/ocaml/idl/datamodel_values.ml
+++ b/ocaml/idl/datamodel_values.ml
@@ -40,7 +40,7 @@ let rec to_rpc v =
| VBool b ->
Rpc.Bool b
| VDateTime d ->
- Rpc.String (Date.to_string d)
+ Rpc.String (Date.to_rfc3339 d)
| VEnum e ->
Rpc.String e
| VMap vvl ->
@@ -94,7 +94,7 @@ let to_db v =
| VBool false ->
String "false"
| VDateTime d ->
- String (Date.to_string d)
+ String (Date.to_rfc3339 d)
| VEnum e ->
String e
| VMap vvl ->
@@ -117,7 +117,7 @@ let gen_empty_db_val t =
| Bool ->
Value.String "false"
| DateTime ->
- Value.String (Date.to_string Date.never)
+ Value.String Date.(to_rfc3339 epoch)
| Enum (_, (enum_value, _) :: _) ->
Value.String enum_value
| Enum (_, []) ->
diff --git a/ocaml/idl/datamodel_vm.ml b/ocaml/idl/datamodel_vm.ml
index 96939c4d5e2..af7aa27b270 100644
--- a/ocaml/idl/datamodel_vm.ml
+++ b/ocaml/idl/datamodel_vm.ml
@@ -339,7 +339,11 @@ let update_snapshot_metadata =
[
(Ref _vm, "vm", "The VM to update")
; (Ref _vm, "snapshot_of", "")
- ; (DateTime, "snapshot_time", "")
+ ; ( DateTime
+ , "snapshot_time"
+ , "The timestamp the snapshot was taken. When a timezone is missing, \
+ UTC is assumed"
+ )
; (String, "transportable_snapshot_id", "")
]
~allowed_roles:_R_POOL_OP ()
@@ -2112,7 +2116,7 @@ let t =
"List pointing to all the VM snapshots."
; field ~writer_roles:_R_VM_POWER_ADMIN ~qualifier:DynamicRO
~in_product_since:rel_orlando
- ~default_value:(Some (VDateTime Date.never)) ~ty:DateTime
+ ~default_value:(Some (VDateTime Date.epoch)) ~ty:DateTime
"snapshot_time" "Date/time when this snapshot was created."
; field ~writer_roles:_R_VM_POWER_ADMIN ~qualifier:DynamicRO
~in_product_since:rel_orlando ~default_value:(Some (VString ""))
diff --git a/ocaml/idl/dune b/ocaml/idl/dune
index 8d337c5c7f2..d971e6597df 100644
--- a/ocaml/idl/dune
+++ b/ocaml/idl/dune
@@ -45,11 +45,12 @@
(action (run %{x} -closed -markdown))
)
-(test
- (name schematest)
+(tests
+ (names schematest test_datetimes)
(modes exe)
- (modules schematest)
+ (modules schematest test_datetimes)
(libraries
+ astring
rpclib.core
rpclib.json
xapi_datamodel
diff --git a/ocaml/idl/json_backend/gen_json.ml b/ocaml/idl/json_backend/gen_json.ml
index 446eeb04b8f..5c8fc0da0ff 100644
--- a/ocaml/idl/json_backend/gen_json.ml
+++ b/ocaml/idl/json_backend/gen_json.ml
@@ -89,7 +89,7 @@ end = struct
| VBool x ->
string_of_bool x
| VDateTime x ->
- Date.to_string x
+ Date.to_rfc3339 x
| VEnum x ->
x
| VMap x ->
diff --git a/ocaml/idl/ocaml_backend/gen_api.ml b/ocaml/idl/ocaml_backend/gen_api.ml
index 90fb78d39dc..5b18d603f4e 100644
--- a/ocaml/idl/ocaml_backend/gen_api.ml
+++ b/ocaml/idl/ocaml_backend/gen_api.ml
@@ -413,9 +413,9 @@ let gen_client_types highapi =
"module Date = struct"
; " open Xapi_stdext_date"
; " include Date"
- ; " let rpc_of_iso8601 x = DateTime (Date.to_string x)"
- ; " let iso8601_of_rpc = function String x | DateTime x -> \
- Date.of_string x | _ -> failwith \"Date.iso8601_of_rpc\""
+ ; " let rpc_of_t x = DateTime (Date.to_rfc3339 x)"
+ ; " let t_of_rpc = function String x | DateTime x -> Date.of_iso8601 \
+ x | _ -> failwith \"Date.t_of_rpc\""
; "end"
]
; [
diff --git a/ocaml/idl/ocaml_backend/gen_db_actions.ml b/ocaml/idl/ocaml_backend/gen_db_actions.ml
index 23c3dc8a747..44542173fe9 100644
--- a/ocaml/idl/ocaml_backend/gen_db_actions.ml
+++ b/ocaml/idl/ocaml_backend/gen_db_actions.ml
@@ -69,7 +69,7 @@ let dm_to_string tys : O.Module.t =
| DT.Bool ->
"string_of_bool"
| DT.DateTime ->
- "Date.to_string"
+ "Date.to_rfc3339"
| DT.Enum (_name, cs) ->
let aux (c, _) =
Printf.sprintf {|| %s -> "%s"|} (OU.constructor_of c) c
@@ -119,7 +119,7 @@ let string_to_dm tys : O.Module.t =
| DT.Bool ->
"bool_of_string"
| DT.DateTime ->
- "fun x -> Date.of_string x"
+ "fun x -> Date.of_iso8601 x"
| DT.Enum (name, cs) ->
let aux (c, _) = "\"" ^ c ^ "\" -> " ^ OU.constructor_of c in
"fun v -> match v with\n "
diff --git a/ocaml/idl/ocaml_backend/gen_test.ml b/ocaml/idl/ocaml_backend/gen_test.ml
index d9824961db0..abf251014f0 100644
--- a/ocaml/idl/ocaml_backend/gen_test.ml
+++ b/ocaml/idl/ocaml_backend/gen_test.ml
@@ -32,7 +32,7 @@ let rec gen_test_type highapi ty =
| DT.Bool ->
"true"
| DT.DateTime ->
- "(Date.of_string \"20120101T00:00:00Z\")"
+ "(Date.of_iso8601 \"20120101T00:00:00Z\")"
| DT.Enum (_, (x, _) :: _) ->
Printf.sprintf "(%s)" (OU.constructor_of x)
| DT.Set (DT.Enum (_, y)) ->
diff --git a/ocaml/idl/ocaml_backend/ocaml_utils.ml b/ocaml/idl/ocaml_backend/ocaml_utils.ml
index 3a6436c67f4..7fe7fe063bc 100644
--- a/ocaml/idl/ocaml_backend/ocaml_utils.ml
+++ b/ocaml/idl/ocaml_backend/ocaml_utils.ml
@@ -128,7 +128,7 @@ let rec ocaml_of_ty = function
| Bool ->
"bool"
| DateTime ->
- "Date.iso8601"
+ "Date.t"
| Set (Record x) ->
alias_of_ty (Record x) ^ " list"
| Set x ->
diff --git a/ocaml/idl/test_datetimes.ml b/ocaml/idl/test_datetimes.ml
new file mode 100644
index 00000000000..ab31f313e5d
--- /dev/null
+++ b/ocaml/idl/test_datetimes.ml
@@ -0,0 +1,47 @@
+module DT = Datamodel_types
+
+let calls_with_datetime_params =
+ let get_messages DT.{name; messages; _} =
+ List.to_seq messages
+ |> Seq.map (fun msg ->
+ DT.{msg with msg_name= Printf.sprintf "%s.%s" name msg.msg_name}
+ )
+ in
+ let with_datetimes DT.{msg_name; msg_params; _} =
+ let cursed_params =
+ List.filter_map
+ (fun param ->
+ if
+ param.DT.param_type = DT.DateTime
+ && not (Astring.String.is_infix ~affix:"UTC" param.param_doc)
+ then
+ Some (msg_name, param.param_name, param.param_doc)
+ else
+ None
+ )
+ msg_params
+ in
+ if cursed_params <> [] then Some (List.to_seq cursed_params) else None
+ in
+
+ Datamodel.all_system
+ |> List.to_seq
+ |> Seq.concat_map get_messages
+ |> Seq.filter_map with_datetimes
+ |> Seq.concat
+
+let () =
+ if not (Seq.is_empty calls_with_datetime_params) then (
+ Printf.printf
+ "\x1b[31;1mERROR\x1b[0m: Found datetime parameters in calls without \
+ proper documentation. It must mention that datetimes are assumed to \
+ have UTC when they do not contain a timezone. Parameters found:\n" ;
+ calls_with_datetime_params
+ |> Seq.iter (fun (call_name, param_name, param_doc) ->
+ Printf.printf "%s (%s): %s\n" call_name param_name param_doc
+ ) ;
+ exit 1
+ ) else
+ Printf.printf
+ "\x1b[32;1mOK\x1b[0m: All datetime parameters in calls have proper \
+ documentation."
diff --git a/ocaml/idl/test_datetimes.mli b/ocaml/idl/test_datetimes.mli
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/ocaml/libs/clock/date.ml b/ocaml/libs/clock/date.ml
index a4a43cde623..c668b0c1fb3 100644
--- a/ocaml/libs/clock/date.ml
+++ b/ocaml/libs/clock/date.ml
@@ -10,6 +10,8 @@
GNU Lesser General Public License for more details.
*)
+module L = Debug.Make (struct let name = __MODULE__ end)
+
let months =
[|
"Jan"
@@ -28,22 +30,18 @@ let months =
let days = [|"Sun"; "Mon"; "Tue"; "Wed"; "Thu"; "Fri"; "Sat"|]
-type print_timezone = Empty | TZ of string
-
-(* we must store the print_type with iso8601 to handle the case where the local time zone is UTC *)
-type t = Ptime.date * Ptime.time * print_timezone
+(* iso8601 allows datetimes to not contain any timezone information.
+ Unfortunately we need to maintain this information because this means that
+ the timestamp cannot be converted back to a timestamp with UTC as a
+ reference. When serializing timezoneless timestamps, the timezone must be
+ avoided yet again. *)
+type tz = int option
-let utc = TZ "Z"
+type t = {t: Ptime.t; tz: tz}
-let of_dt print_type dt =
- let date, time = dt in
- (date, time, print_type)
-
-let to_dt (date, time, _) = (date, time)
+let utc = Some 0
let best_effort_iso8601_to_rfc3339 x =
- (* (a) add dashes
- * (b) add UTC tz if no tz provided *)
let x =
try
Scanf.sscanf x "%04d%02d%02dT%s" (fun y mon d rest ->
@@ -60,30 +58,39 @@ let best_effort_iso8601_to_rfc3339 x =
in
match tz with
| None | Some "" ->
- (* the caller didn't specify a tz. we must try to add one so that ptime can at least attempt to parse *)
- (Printf.sprintf "%sZ" x, Empty)
- | Some tz ->
- (x, TZ tz)
+ (* the caller didn't specify a tz, assume Coordinatel Universal Time *)
+ Printf.sprintf "%sZ" x
+ | Some _ ->
+ x
let of_iso8601 x =
- let rfc3339, print_timezone = best_effort_iso8601_to_rfc3339 x in
+ let rfc3339 = best_effort_iso8601_to_rfc3339 x in
match Ptime.of_rfc3339 rfc3339 |> Ptime.rfc3339_error_to_msg with
| Error _ ->
invalid_arg (Printf.sprintf "%s: %s" __FUNCTION__ x)
- | Ok (t, tz, _) -> (
- match tz with
- | None | Some 0 ->
- Ptime.to_date_time t |> of_dt print_timezone
- | Some _ ->
- invalid_arg (Printf.sprintf "%s: %s" __FUNCTION__ x)
- )
-
-let to_rfc3339 ((y, mon, d), ((h, min, s), _), print_type) =
- match print_type with
- | TZ tz ->
- Printf.sprintf "%04i%02i%02iT%02i:%02i:%02i%s" y mon d h min s tz
- | Empty ->
- Printf.sprintf "%04i%02i%02iT%02i:%02i:%02i" y mon d h min s
+ | Ok (t, tz, _) ->
+ {t; tz}
+
+let print_tz tz_s =
+ match tz_s with
+ | None ->
+ ""
+ | Some 0 ->
+ "Z"
+ | Some tz ->
+ let tz_sign = if tz < 0 then '-' else '+' in
+ let all_tz_minutes = tz / 60 |> Int.abs in
+ let tz_h = all_tz_minutes / 60 in
+ let tz_min = all_tz_minutes mod 60 in
+ Printf.sprintf "%c%02d:%02d" tz_sign tz_h tz_min
+
+let to_rfc3339 {t; tz} =
+ (* Must be compatible with iso8601 as well. Because some client limitations,
+ the hyphens between year, month and day have to be absent
+ *)
+ let (y, mon, d), ((h, min, s), _) = Ptime.to_date_time ?tz_offset_s:tz t in
+ let tz = print_tz tz in
+ Printf.sprintf "%04i%02i%02iT%02i:%02i:%02i%s" y mon d h min s tz
(* Extracted from tondering.dk/claus/cal/chrweek.php#calcdow *)
let weekday ~year ~mon ~day =
@@ -92,29 +99,25 @@ let weekday ~year ~mon ~day =
let m = mon + (12 * a) - 2 in
(day + y + (y / 4) - (y / 100) + (y / 400) + (31 * m / 12)) mod 7
-let to_rfc822 ((year, mon, day), ((h, min, s), _), print_type) =
- let timezone =
- match print_type with Empty | TZ "Z" -> "GMT" | TZ tz -> tz
+let to_rfc822 {t; tz} =
+ let (year, mon, day), ((h, min, s), _) =
+ Ptime.to_date_time ?tz_offset_s:tz t
in
+ let timezone = match print_tz tz with "Z" -> "GMT" | tz -> tz in
let weekday = weekday ~year ~mon ~day in
Printf.sprintf "%s, %d %s %d %02d:%02d:%02d %s" days.(weekday) day
months.(mon - 1)
year h min s timezone
-let to_ptime_t t =
- match to_dt t |> Ptime.of_date_time with
- | Some t ->
+let to_ptime = function
+ | {t; tz= None} as d ->
+ L.warn "%s: Date %s converted to POSIX time, but timezone is missing"
+ __FUNCTION__ (to_rfc3339 d) ;
+ t
+ | {t; tz= Some _} ->
t
- | None ->
- let _, (_, offset), _ = t in
- invalid_arg
- (Printf.sprintf "%s: dt='%s', offset='%i' is invalid" __FUNCTION__
- (to_rfc3339 t) offset
- )
-
-let to_ptime = to_ptime_t
-let of_ptime t = Ptime.to_date_time t |> of_dt utc
+let of_ptime t = {t; tz= utc}
let of_unix_time s =
match Ptime.of_float_s s with
@@ -123,24 +126,22 @@ let of_unix_time s =
| Some t ->
of_ptime t
-let to_unix_time t = to_ptime_t t |> Ptime.to_float_s
+let to_unix_time t = to_ptime t |> Ptime.to_float_s
-let _localtime current_tz_offset t =
- let tz_offset_s = current_tz_offset |> Option.value ~default:0 in
- let localtime = t |> Ptime.to_date_time ~tz_offset_s |> of_dt Empty in
- let _, (_, localtime_offset), _ = localtime in
- if localtime_offset <> tz_offset_s then
- invalid_arg
- (Printf.sprintf "%s: offsets don't match. offset='%i', t='%s'"
- __FUNCTION__ tz_offset_s (Ptime.to_rfc3339 t)
- ) ;
- localtime
+let strip_tz tz t =
+ let t =
+ match tz with
+ | None ->
+ t
+ | Some tz ->
+ Ptime.Span.of_int_s tz |> Ptime.add_span t |> Option.value ~default:t
+ in
+ {t; tz= None}
-let _localtime_string current_tz_offset t =
- _localtime current_tz_offset t |> to_rfc3339
+let _localtime_string tz t = strip_tz tz t |> to_rfc3339
let localtime () =
- _localtime (Ptime_clock.current_tz_offset_s ()) (Ptime_clock.now ())
+ strip_tz (Ptime_clock.current_tz_offset_s ()) (Ptime_clock.now ())
let now () = of_ptime (Ptime_clock.now ())
@@ -152,19 +153,19 @@ let is_later ~than t = Ptime.is_later ~than:(to_ptime than) (to_ptime t)
let diff a b = Ptime.diff (to_ptime a) (to_ptime b)
-let compare_print_tz a b =
+let compare_tz a b =
match (a, b) with
- | Empty, Empty ->
+ | None, None ->
0
- | TZ a_s, TZ b_s ->
- String.compare a_s b_s
- | Empty, TZ _ ->
+ | Some a_s, Some b_s ->
+ Int.compare a_s b_s
+ | None, Some _ ->
-1
- | TZ _, Empty ->
+ | Some _, None ->
1
-let compare ((_, _, a_z) as a) ((_, _, b_z) as b) =
+let compare a b =
let ( > ) a b = if a = 0 then b else a in
- Ptime.compare (to_ptime a) (to_ptime b) > compare_print_tz a_z b_z
+ Ptime.compare (to_ptime a) (to_ptime b) > compare_tz a.tz b.tz
-let eq x y = compare x y = 0
+let equal x y = if x == y then true else compare x y = 0
diff --git a/ocaml/libs/clock/date.mli b/ocaml/libs/clock/date.mli
index 2a0123813b3..1ba0f19c9d9 100644
--- a/ocaml/libs/clock/date.mli
+++ b/ocaml/libs/clock/date.mli
@@ -12,24 +12,32 @@
* GNU Lesser General Public License for more details.
*)
-(** date-time with support for keeping timezone for ISO 8601 conversion *)
+(** Nanosecond-precision POSIX timestamps, allows datetimes with unspecified
+ timezones. These are needed to produce and accept ISO 8601 datetimes without
+ timezones, but because the timezone is not known they do not share a common
+ point of time with any other timestamps they cannot be converted to unix
+ time, or be compared with other timestamps. All other timestamps have a
+ timezone attached to them, which will be used to serialize them to a
+ datetime string. This timezone is determined when creating a value and
+ cannot be changed. For timestamps created from datetime strings, the
+ timezone is maintained. For all other values UTC is used. *)
type t
(** Conversions *)
val of_ptime : Ptime.t -> t
-(** Convert ptime to time in UTC *)
+(** Converts ptime to date *)
val to_ptime : t -> Ptime.t
(** Convert date/time to a ptime value: the number of seconds since 00:00:00
- UTC, 1 Jan 1970. Assumes the underlying {!t} is in UTC *)
+ UTC, 1 Jan 1970. When {!t} lacks a timezone, UTC is assumed *)
val of_unix_time : float -> t
(** Convert calendar time [x] (as returned by e.g. Unix.time), to time in UTC *)
val to_unix_time : t -> float
(** Convert date/time to a unix timestamp: the number of seconds since
- 00:00:00 UTC, 1 Jan 1970. Assumes the underlying {!t} is in UTC *)
+ 00:00:00 UTC, 1 Jan 1970. When {!t} lacks a timezone, UTC is assumed *)
val to_rfc822 : t -> string
(** Convert date/time to email-formatted (RFC 822) string. *)
@@ -39,38 +47,42 @@ val to_rfc3339 : t -> string
the ISO 8601 format *)
val of_iso8601 : string -> t
-(** Convert ISO 8601 formatted string to a date/time value. Does not accept a
- timezone annotated datetime - i.e. string must be UTC, and end with a Z *)
+(** Convert ISO 8601 formatted string to a date/time value. Timezone can be
+ missing from the string, but that means some conversions will assume UTC,
+ which might be incorrect *)
val epoch : t
-(** 00:00:00 UTC, 1 Jan 1970, in UTC *)
+(** 00:00:00 UTC, 1 Jan 1970 *)
val now : unit -> t
-(** Count the number of seconds passed since 00:00:00 UTC, 1 Jan 1970, in UTC *)
+(** Count the number of seconds passed since 00:00:00 UTC, 1 Jan 1970 *)
val _localtime_string : Ptime.tz_offset_s option -> Ptime.t -> string
(** exposed for testing *)
val localtime : unit -> t
-(** Count the number of seconds passed since 00:00:00 UTC, 1 Jan 1970, in local
- time *)
+(** Local date time, the timezone is stripped. Do not use this call in new
+ code. *)
(** Comparisons *)
-val eq : t -> t -> bool
-(** [eq a b] returns whether [a] and [b] are equal *)
+val equal : t -> t -> bool
+(** [equal a b] returns whether [a] and [b] are equal. Timestamps that are not
+ on UTC will only be equal to the values in their same memory position. *)
val compare : t -> t -> int
(** [compare a b] returns -1 if [a] is earlier than [b], 1 if [a] is later than
- [b] or the ordering of the timezone printer *)
+ [b] or which timeone is sooner. When [a] or [b] lack a timezone, UTC is
+ assumed *)
val is_earlier : than:t -> t -> bool
(** [is_earlier ~than a] returns whether the timestamp [a] happens before
- [than] *)
+ [than]. When [than] or [b] lack a timezone, UTC is assumed. *)
val is_later : than:t -> t -> bool
-(** [is_later ~than a] returns whether the timestamp [a] happens after [than]
- *)
+(** [is_later ~than a] returns whether the timestamp [a] happens after [than].
+ When [than] or [b] lack a timezone, UTC is assumed. *)
val diff : t -> t -> Ptime.Span.t
-(** [diff a b] returns the span of time corresponding to [a - b] *)
+(** [diff a b] returns the span of time corresponding to [a - b]. When [than]
+ or [b] lack a timezone, UTC is assumed. *)
diff --git a/ocaml/libs/clock/dune b/ocaml/libs/clock/dune
index 76285033f35..a2afef36460 100644
--- a/ocaml/libs/clock/dune
+++ b/ocaml/libs/clock/dune
@@ -8,6 +8,7 @@
mtime.clock.os
(re_export ptime)
ptime.clock.os
+ xapi-log
)
)
diff --git a/ocaml/libs/clock/test_date.ml b/ocaml/libs/clock/test_date.ml
index 78f673f635c..9318f44af54 100644
--- a/ocaml/libs/clock/test_date.ml
+++ b/ocaml/libs/clock/test_date.ml
@@ -10,6 +10,28 @@ let dash_time_str = "2020-04-07T08:28:32Z"
let no_dash_utc_time_str = "20200407T08:28:32Z"
+let best_effort_iso8601_to_rfc3339 x =
+ let x =
+ try
+ Scanf.sscanf x "%04d%02d%02dT%s" (fun y mon d rest ->
+ Printf.sprintf "%04d-%02d-%02dT%s" y mon d rest
+ )
+ with _ -> x
+ in
+ let tz =
+ try
+ Scanf.sscanf x "%04d-%02d-%02dT%02d:%02d:%02d%s" (fun _ _ _ _ _ _ tz ->
+ Some tz
+ )
+ with _ -> None
+ in
+ match tz with
+ | None | Some "" ->
+ (* the caller didn't specify a tz, use the Unqualified Local Time *)
+ Printf.sprintf "%s-00:00" x
+ | Some _ ->
+ x
+
let tests =
let test_of_unix_time_invertible () =
let non_int_time = 1586245987.70200706 in
@@ -17,20 +39,24 @@ let tests =
check_float "to_unix_time inverts of_unix_time" time
(time |> of_unix_time |> to_unix_time) ;
check_true "of_unix_time inverts to_unix_time"
- @@ eq (time |> of_unix_time)
+ @@ equal (time |> of_unix_time)
(time |> of_unix_time |> to_unix_time |> of_unix_time)
in
- let test_only_utc () =
+ let test_iso8601 () =
let utc = "2020-12-20T18:10:19Z" in
let _ = of_iso8601 utc in
(* UTC is valid *)
let non_utc = "2020-12-20T18:10:19+02:00" in
- let exn =
- Invalid_argument "Clock__Date.of_iso8601: 2020-12-20T18:10:19+02:00"
+ let _ = of_iso8601 non_utc in
+ ()
+ in
+ let test_roundtrip_conversion () =
+ let non_utc = ["20201220T18:10:19+02:00"; "20201220T18:10:19-08:45"] in
+ let test spec =
+ let result = spec |> of_iso8601 |> to_rfc3339 in
+ Alcotest.(check string) "Roundtrip conversion be consistent" spec result
in
- Alcotest.check_raises "only UTC is accepted" exn (fun () ->
- of_iso8601 non_utc |> ignore
- )
+ List.iter test non_utc
in
let test_ca333908 () =
check_float "dash time and no dash time represent the same unix timestamp"
@@ -41,7 +67,7 @@ let tests =
check_string "to_rfc3339 inverts of_iso8601" no_dash_utc_time_str
(no_dash_utc_time_str |> of_iso8601 |> to_rfc3339) ;
check_true "of_iso8601 inverts to_rfc3339"
- (eq
+ (equal
(no_dash_utc_time_str |> of_iso8601)
(no_dash_utc_time_str |> of_iso8601 |> to_rfc3339 |> of_iso8601)
)
@@ -51,6 +77,21 @@ let tests =
check_string "to_rfc3339 is backwards compatible" no_dash_utc_time_str
(dash_time_str |> of_iso8601 |> to_rfc3339)
in
+ let test_localtime () =
+ let time = localtime () in
+ match
+ time
+ |> to_rfc3339
+ |> best_effort_iso8601_to_rfc3339
+ |> Ptime.of_rfc3339
+ |> Ptime.rfc3339_error_to_msg
+ with
+ | Ok (_, tz, _) ->
+ Alcotest.(check @@ option int)
+ "localtime generates a timestamp without timezone" None tz
+ | Error (`Msg msg) ->
+ Alcotest.failf "Unexpected error: %s" msg
+ in
let test_localtime_string () =
let[@warning "-8"] (Ok (t, _, _)) =
Ptime.of_rfc3339 "2020-04-07T09:01:28Z"
@@ -82,24 +123,33 @@ let tests =
(String.contains localtime_string 'Z')
in
let test_xsi894 () =
+ let canonical = "20201210T17:19:20Z" in
let missing_tz_no_dash = "20201210T17:19:20" in
let missing_tz_dash = "2020-12-10T17:19:20" in
- check_string "can process missing tz no dash" missing_tz_no_dash
+ check_string
+ "Timestamp without timezones nor dashes is accepted, gets converted to \
+ UTC"
+ canonical
(missing_tz_no_dash |> of_iso8601 |> to_rfc3339) ;
- check_string "can process missing tz with dashes, but return without dashes"
- missing_tz_no_dash
- (missing_tz_dash |> of_iso8601 |> to_rfc3339) ;
- check_float "to_unix_time assumes UTC" 1607620760.
- (missing_tz_no_dash |> of_iso8601 |> to_unix_time) ;
- let localtime' = localtime () in
- check_string "to_rfc3339 inverts of_iso8601 for localtime"
- (localtime' |> to_rfc3339)
- (localtime' |> to_rfc3339 |> of_iso8601 |> to_rfc3339)
+ check_string
+ "Timestamp without timezones, and dashes is accepted, gets converted to \
+ UTC"
+ canonical
+ (missing_tz_dash |> of_iso8601 |> to_rfc3339)
in
let test_email_date (unix_timestamp, expected) =
let formatted = of_unix_time unix_timestamp |> to_rfc822 in
check_string "String is properly RFC-822-formatted" expected formatted
in
+ let test_no_timezone_to_unix () =
+ (* this is allowed, but it will print a warning to stdout *)
+ let missing_tz_no_dash = "20201210T17:19:20" in
+ let with_tz_no_dash = "20201210T17:19:20Z" in
+ let to_unix_time dt = dt |> of_iso8601 |> to_unix_time in
+ check_float "Datetime without timezone assumes it's in UTC"
+ (to_unix_time with_tz_no_dash)
+ (to_unix_time missing_tz_no_dash)
+ in
let test_email_dates () =
let dates =
[
@@ -113,7 +163,8 @@ let tests =
in
[
("test_of_unix_time_invertible", `Quick, test_of_unix_time_invertible)
- ; ("test_only_utc", `Quick, test_only_utc)
+ ; ("test_only_utc", `Quick, test_iso8601)
+ ; ("Roundtrip conversion", `Quick, test_roundtrip_conversion)
; ("test_ca333908", `Quick, test_ca333908)
; ( "test_of_iso8601_invertible_when_no_dashes"
, `Quick
@@ -123,9 +174,14 @@ let tests =
, `Quick
, test_to_rfc3339_backwards_compatibility
)
+ ; ("localtime is printed without timezone", `Quick, test_localtime)
; ("test_localtime_string", `Quick, test_localtime_string)
; ("test_ca342171", `Quick, test_ca342171)
- ; ("test_xsi894", `Quick, test_xsi894)
+ ; ("Parsing datetimes without timezones", `Quick, test_xsi894)
+ ; ( "Date w/o timezone to POSIX time conversion"
+ , `Quick
+ , test_no_timezone_to_unix
+ )
; ("RFC 822 formatting", `Quick, test_email_dates)
]
diff --git a/ocaml/libs/http-lib/xMLRPC.ml b/ocaml/libs/http-lib/xMLRPC.ml
index a918f9b4e13..e9e425b976f 100644
--- a/ocaml/libs/http-lib/xMLRPC.ml
+++ b/ocaml/libs/http-lib/xMLRPC.ml
@@ -68,7 +68,7 @@ module To = struct
let boolean b = value (box "boolean" [pcdata (if b then "1" else "0")])
let datetime s =
- value (box "dateTime.iso8601" [pcdata (Xapi_stdext_date.Date.to_string s)])
+ value (box "dateTime.iso8601" [pcdata (Xapi_stdext_date.Date.to_rfc3339 s)])
let double x =
let txt =
@@ -197,7 +197,7 @@ module From = struct
let boolean = value (singleton ["boolean"] (( <> ) (Xml.PCData "0")))
let datetime x =
- Xapi_stdext_date.Date.of_string
+ Xapi_stdext_date.Date.of_iso8601
(value (singleton ["dateTime.iso8601"] (pcdata id)) x)
let double = value (singleton ["double"] (pcdata float_of_string))
diff --git a/ocaml/libs/http-lib/xMLRPC.mli b/ocaml/libs/http-lib/xMLRPC.mli
index c8a7ca32af6..165f2e6ec52 100644
--- a/ocaml/libs/http-lib/xMLRPC.mli
+++ b/ocaml/libs/http-lib/xMLRPC.mli
@@ -59,7 +59,7 @@ module To : sig
val boolean : bool -> xmlrpc
(** Marshal a boolean. *)
- val datetime : Xapi_stdext_date.Date.iso8601 -> xmlrpc
+ val datetime : Xapi_stdext_date.Date.t -> xmlrpc
(** Marshal a date-time. *)
val double : float -> xmlrpc
@@ -98,7 +98,7 @@ module From : sig
val boolean : xmlrpc -> bool
(** Parse a boolean. *)
- val datetime : xmlrpc -> Xapi_stdext_date.Date.iso8601
+ val datetime : xmlrpc -> Xapi_stdext_date.Date.t
(** Parse a date-time. *)
val double : xmlrpc -> float
diff --git a/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.ml b/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.ml
index 45e9bba5efb..ef0f98ce13a 100644
--- a/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.ml
+++ b/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.ml
@@ -28,6 +28,8 @@ let rfc822_of_float = of_unix_time
let rfc822_to_string = to_rfc822
+let eq = equal
+
type iso8601 = t
type rfc822 = t
diff --git a/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.mli b/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.mli
index 62e894808bf..7fb29404306 100644
--- a/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.mli
+++ b/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.mli
@@ -57,8 +57,8 @@ val localtime : unit -> t
(** Comparisons *)
-val eq : t -> t -> bool
-(** [eq a b] returns whether [a] and [b] are equal *)
+val equal : t -> t -> bool
+(** [equal a b] returns whether [a] and [b] are equal *)
val compare : t -> t -> int
(** [compare a b] returns -1 if [a] is earlier than [b], 1 if [a] is later than
@@ -77,29 +77,39 @@ val diff : t -> t -> Ptime.Span.t
(** Deprecated bindings, these will be removed in a future release: *)
+val eq : t -> t -> bool
+[@@deprecated "Use Date.equal"]
+(** [eq a b] returns whether [a] and [b] are equal *)
+
val rfc822_to_string : t -> string
+[@@deprecated "Use Date.to_rfc822"]
(** Same as {!to_rfc822} *)
val rfc822_of_float : float -> t
+[@@deprecated "Use Date.of_unix_time"]
(** Same as {!of_unix_time} *)
val of_float : float -> t
+[@@deprecated "Use Date.of_unix_time"]
(** Same as {!of_unix_time} *)
val to_float : t -> float
+[@@deprecated "Use Date.to_unix_time"]
(** Same as {!to_unix_time} *)
val to_string : t -> string
+[@@deprecated "Use Date.to_rfc3339"]
(** Same as {!to_rfc3339} *)
val of_string : string -> t
+[@@deprecated "Use Date.of_iso8601"]
(** Same as {!of_iso8601} *)
-val never : t
+val never : t [@@deprecated "Use Date.epoch"]
(** Same as {!epoch} *)
(** Deprecated alias for {!t} *)
-type iso8601 = t
+type iso8601 = t [@@deprecated "Use Date.t"]
(** Deprecated alias for {!t} *)
-type rfc822 = t
+type rfc822 = t [@@deprecated "Use Date.t"]
diff --git a/ocaml/license/daily_license_check.ml b/ocaml/license/daily_license_check.ml
index b107bfef755..3b6edecbb3e 100644
--- a/ocaml/license/daily_license_check.ml
+++ b/ocaml/license/daily_license_check.ml
@@ -13,7 +13,7 @@ let get_hosts all_license_params threshold =
List.fold_left
(fun acc (name_label, license_params) ->
let expiry = List.assoc "expiry" license_params in
- let expiry = Xapi_stdext_date.Date.(to_float (of_string expiry)) in
+ let expiry = Xapi_stdext_date.Date.(to_unix_time (of_iso8601 expiry)) in
if expiry < threshold then
name_label :: acc
else
@@ -23,7 +23,7 @@ let get_hosts all_license_params threshold =
let check_license now pool_license_state all_license_params =
let expiry = List.assoc "expiry" pool_license_state in
- let expiry = Xapi_stdext_date.Date.(to_float (of_string expiry)) in
+ let expiry = Xapi_stdext_date.Date.(to_unix_time (of_iso8601 expiry)) in
let days = days_to_expiry now expiry in
if days <= 0. then
Expired (get_hosts all_license_params now)
diff --git a/ocaml/quicktest/qt.ml b/ocaml/quicktest/qt.ml
index 7485cef15d4..3b6b7cd9743 100644
--- a/ocaml/quicktest/qt.ml
+++ b/ocaml/quicktest/qt.ml
@@ -100,9 +100,9 @@ module Time = struct
let now () = Unix.gettimeofday ()
- let of_field = Xapi_stdext_date.Date.to_float
+ let of_field = Xapi_stdext_date.Date.to_unix_time
- let pp t = Xapi_stdext_date.Date.of_float t |> Xapi_stdext_date.Date.to_string
+ let pp t = Xapi_stdext_date.Date.(of_unix_time t |> to_rfc3339)
let check t ~after ~before =
Alcotest.(check bool)
@@ -269,7 +269,7 @@ module VDI = struct
; ( `Same
, "snapshot_time"
, fun vdi ->
- vdi.API.vDI_snapshot_time |> Xapi_stdext_date.Date.to_string
+ vdi.API.vDI_snapshot_time |> Xapi_stdext_date.Date.to_rfc3339
)
; (`Same, "virtual_size", fun vdi -> vdi.API.vDI_location)
]
diff --git a/ocaml/quicktest/qt.mli b/ocaml/quicktest/qt.mli
index 15dbb785f28..5ba4e8c68a0 100644
--- a/ocaml/quicktest/qt.mli
+++ b/ocaml/quicktest/qt.mli
@@ -34,7 +34,7 @@ module Time : sig
val now : unit -> t
- val of_field : Xapi_stdext_date.Date.iso8601 -> t
+ val of_field : Xapi_stdext_date.Date.t -> t
val pp : t -> string
diff --git a/ocaml/quicktest/quicktest_date.ml b/ocaml/quicktest/quicktest_date.ml
index 7a7e6b7ba5e..19ff9153088 100644
--- a/ocaml/quicktest/quicktest_date.ml
+++ b/ocaml/quicktest/quicktest_date.ml
@@ -3,9 +3,7 @@ module Date = Xapi_stdext_date.Date
let test_host_get_server_localtime rpc session_id () =
let host = Client.Host.get_by_uuid ~rpc ~session_id ~uuid:Qt.localhost_uuid in
- let (_ : Date.iso8601) =
- Client.Host.get_server_localtime ~rpc ~session_id ~host
- in
+ let (_ : Date.t) = Client.Host.get_server_localtime ~rpc ~session_id ~host in
()
let test_message_get_since rpc session_id () =
@@ -14,7 +12,7 @@ let test_message_get_since rpc session_id () =
Forkhelpers.execute_command_get_output "/bin/date"
[Printf.sprintf "+%s" format'; "-d"; "yesterday"]
in
- let yesterday = String.trim stdout |> Date.of_string in
+ let yesterday = String.trim stdout |> Date.of_iso8601 in
let (_ : ('a API.Ref.t * API.message_t) list) =
Client.Message.get_since ~rpc ~session_id ~since:yesterday
in
@@ -25,6 +23,7 @@ let test_message_get_since rpc session_id () =
; "%Y-%m-%dT%H:%M:%S"
; "%Y%m%dT%H:%M:%SZ"
; "%Y%m%dT%H:%M:%S"
+ ; "%Y%m%dT%H:%M:%S-12:00"
]
|> List.iter test_with_format
diff --git a/ocaml/quicktest/quicktest_event.ml b/ocaml/quicktest/quicktest_event.ml
index f844db3e72c..a99f71bf752 100644
--- a/ocaml/quicktest/quicktest_event.ml
+++ b/ocaml/quicktest/quicktest_event.ml
@@ -381,7 +381,7 @@ let event_message_test rpc session_id () =
) ;
let messages =
Client.Client.Message.get ~rpc ~session_id ~cls ~obj_uuid
- ~since:Xapi_stdext_date.Date.never
+ ~since:Xapi_stdext_date.Date.epoch
in
let has_msg m = List.exists (fun (r, _) -> r = m) messages in
Alcotest.(check bool)
diff --git a/ocaml/quicktest/quicktest_vdi.ml b/ocaml/quicktest/quicktest_vdi.ml
index a648495eced..a11e1b2ce05 100644
--- a/ocaml/quicktest/quicktest_vdi.ml
+++ b/ocaml/quicktest/quicktest_vdi.ml
@@ -139,7 +139,7 @@ let vdi_bad_introduce rpc session_id sr_info () =
~location:(Ref.string_of (Ref.make ()))
~xenstore_data:[] ~sm_config:[] ~managed:true ~virtual_size:0L
~physical_utilisation:0L ~metadata_of_pool:Ref.null
- ~is_a_snapshot:false ~snapshot_time:Xapi_stdext_date.Date.never
+ ~is_a_snapshot:false ~snapshot_time:Xapi_stdext_date.Date.epoch
~snapshot_of:Ref.null
in
Alcotest.fail
@@ -161,7 +161,7 @@ let vdi_bad_introduce rpc session_id sr_info () =
~other_config:[] ~location:vdir.API.vDI_location ~xenstore_data:[]
~sm_config:[] ~managed:true ~virtual_size:0L
~physical_utilisation:0L ~metadata_of_pool:Ref.null
- ~is_a_snapshot:false ~snapshot_time:Xapi_stdext_date.Date.never
+ ~is_a_snapshot:false ~snapshot_time:Xapi_stdext_date.Date.epoch
~snapshot_of:Ref.null
in
Alcotest.fail
diff --git a/ocaml/sdk-gen/csharp/gen_csharp_binding.ml b/ocaml/sdk-gen/csharp/gen_csharp_binding.ml
index ff390468130..edaa3a7c7f9 100644
--- a/ocaml/sdk-gen/csharp/gen_csharp_binding.ml
+++ b/ocaml/sdk-gen/csharp/gen_csharp_binding.ml
@@ -1206,7 +1206,7 @@ and get_default_value_opt field =
Printf.sprintf
"DateTime.ParseExact(\"%s\", \"yyyyMMddTHH:mm:ssZ\", \
CultureInfo.InvariantCulture)"
- (Date.to_string y)
+ (Date.to_rfc3339 y)
]
| VEnum y ->
[enum_of_wire y]
diff --git a/ocaml/tests/alerts/test_alert_certificate_check.ml b/ocaml/tests/alerts/test_alert_certificate_check.ml
index b35dcd362a5..ce84cc672d2 100644
--- a/ocaml/tests/alerts/test_alert_certificate_check.ml
+++ b/ocaml/tests/alerts/test_alert_certificate_check.ml
@@ -14,7 +14,7 @@
open Certificate_check
-let date_of = Xapi_stdext_date.Date.of_string
+let date_of = Xapi_stdext_date.Date.of_iso8601
let check_time = date_of "20200201T02:00:00Z"
diff --git a/ocaml/tests/alerts/test_daily_license_check.ml b/ocaml/tests/alerts/test_daily_license_check.ml
index 866830b1059..067d93288ce 100644
--- a/ocaml/tests/alerts/test_daily_license_check.ml
+++ b/ocaml/tests/alerts/test_daily_license_check.ml
@@ -37,7 +37,7 @@ let expiry =
Alcotest.testable pp_expiry equals
let check_time =
- Xapi_stdext_date.Date.(to_float (of_string "20160601T04:00:00Z"))
+ Xapi_stdext_date.Date.(to_unix_time (of_iso8601 "20160601T04:00:00Z"))
let test_expiry ((pool_license_state, all_license_params), expected) () =
let result = check_license check_time pool_license_state all_license_params in
diff --git a/ocaml/tests/alerts/test_expiry_alert.ml b/ocaml/tests/alerts/test_expiry_alert.ml
index ece31122b78..2c3fa283be8 100644
--- a/ocaml/tests/alerts/test_expiry_alert.ml
+++ b/ocaml/tests/alerts/test_expiry_alert.ml
@@ -14,7 +14,7 @@
open Expiry_alert
-let date_of = Xapi_stdext_date.Date.of_string
+let date_of = Xapi_stdext_date.Date.of_iso8601
let test_expired = ("TEST_EXPIRED", 1L)
diff --git a/ocaml/tests/common/test_common.ml b/ocaml/tests/common/test_common.ml
index 1c1685f693d..293317518a4 100644
--- a/ocaml/tests/common/test_common.ml
+++ b/ocaml/tests/common/test_common.ml
@@ -296,7 +296,7 @@ let make_pool ~__context ~master ?(name_label = "") ?(name_description = "")
?(repository_proxy_username = "") ?(repository_proxy_password = Ref.null)
?(migration_compression = false) ?(coordinator_bias = true)
?(telemetry_uuid = Ref.null) ?(telemetry_frequency = `weekly)
- ?(telemetry_next_collection = API.Date.never)
+ ?(telemetry_next_collection = API.Date.epoch)
?(last_update_sync = API.Date.epoch) ?(update_sync_frequency = `daily)
?(update_sync_day = 0L) ?(update_sync_enabled = false)
?(recommendations = []) () =
@@ -393,7 +393,7 @@ let make_vdi ~__context ?(ref = Ref.make ()) ?(uuid = make_uuid ())
?(read_only = false) ?(other_config = []) ?(storage_lock = false)
?(location = "") ?(managed = false) ?(missing = false) ?(parent = Ref.null)
?(xenstore_data = []) ?(sm_config = []) ?(is_a_snapshot = false)
- ?(snapshot_of = Ref.null) ?(snapshot_time = API.Date.never) ?(tags = [])
+ ?(snapshot_of = Ref.null) ?(snapshot_time = API.Date.epoch) ?(tags = [])
?(allow_caching = true) ?(on_boot = `persist)
?(metadata_of_pool = Ref.make ()) ?(metadata_latest = true)
?(is_tools_iso = false) ?(cbt_enabled = false) () =
@@ -516,9 +516,9 @@ let make_pool_update ~__context ?(ref = Ref.make ()) ?(uuid = make_uuid ())
let make_session ~__context ?(ref = Ref.make ()) ?(uuid = make_uuid ())
?(this_host = Ref.null) ?(this_user = Ref.null)
- ?(last_active = API.Date.never) ?(pool = false) ?(other_config = [])
+ ?(last_active = API.Date.epoch) ?(pool = false) ?(other_config = [])
?(is_local_superuser = false) ?(subject = Ref.null)
- ?(validation_time = API.Date.never) ?(auth_user_sid = "")
+ ?(validation_time = API.Date.epoch) ?(auth_user_sid = "")
?(auth_user_name = "") ?(rbac_permissions = []) ?(parent = Ref.null)
?(originator = "test") ?(client_certificate = false) () =
Db.Session.create ~__context ~ref ~uuid ~this_host ~this_user ~last_active
diff --git a/ocaml/tests/test_client.ml b/ocaml/tests/test_client.ml
index cdfa7690f79..1c3137721b8 100644
--- a/ocaml/tests/test_client.ml
+++ b/ocaml/tests/test_client.ml
@@ -13,7 +13,7 @@ let make_client_params ~__context =
let rpc = Api_server.Server.dispatch_call req Unix.stdout in
let session_id =
let session_id = Ref.make () in
- let now = Xapi_stdext_date.Date.of_float (Unix.time ()) in
+ let now = Xapi_stdext_date.Date.now () in
let (_ : _ API.Ref.t) =
Test_common.make_session ~__context ~ref:session_id
~this_host:(Helpers.get_localhost ~__context)
diff --git a/ocaml/tests/test_pool_license.ml b/ocaml/tests/test_pool_license.ml
index fbba9c74e36..aad9a145c11 100644
--- a/ocaml/tests/test_pool_license.ml
+++ b/ocaml/tests/test_pool_license.ml
@@ -29,22 +29,24 @@ let string_of_date_opt = function
| None ->
"None"
| Some date ->
- Printf.sprintf "Some %s" (Date.to_string date)
+ Printf.sprintf "Some %s" (Date.to_rfc3339 date)
-let f2d = Date.of_float
+let f2d = Date.of_unix_time
-let f2d2s f = f |> Date.of_float |> Date.to_string
+let f2d2s f = f |> Date.of_unix_time |> Date.to_rfc3339
let edition_to_int = [("edition1", 1); ("edition2", 2); ("edition3", 3)]
module CompareDates = Generic.MakeStateless (struct
module Io = struct
- type input_t = Date.iso8601 option * Date.iso8601 option
+ type input_t = Date.t option * Date.t option
type output_t = int
let string_of_input_t =
- Test_printers.(assoc_pair (option Date.to_string) (option Date.to_string))
+ Test_printers.(
+ assoc_pair (option Date.to_rfc3339) (option Date.to_rfc3339)
+ )
let string_of_output_t = Test_printers.int
end
@@ -66,13 +68,13 @@ end)
module PoolExpiryDate = Generic.MakeStateful (struct
module Io = struct
- type input_t = Date.iso8601 option list
+ type input_t = Date.t option list
- type output_t = Date.iso8601 option
+ type output_t = Date.t option
- let string_of_input_t = Test_printers.(list (option Date.to_string))
+ let string_of_input_t = Test_printers.(list (option Date.to_rfc3339))
- let string_of_output_t = Test_printers.option Date.to_string
+ let string_of_output_t = Test_printers.option Date.to_rfc3339
end
module State = Test_state.XapiDb
@@ -86,7 +88,7 @@ module PoolExpiryDate = Generic.MakeStateful (struct
| None ->
[]
| Some date ->
- [("expiry", Date.to_string date)]
+ [("expiry", Date.to_rfc3339 date)]
in
let (_ : API.ref_host) =
Test_common.make_host ~__context ~edition:"edition1" ~license_params
@@ -201,10 +203,10 @@ module PoolLicenseState = Generic.MakeStateful (struct
| None ->
"never"
| Some date ->
- if date = Date.of_float License_check.never then
+ if date = Date.of_unix_time License_check.never then
"never"
else
- Date.to_string date
+ Date.to_rfc3339 date
in
(pool_edition, pool_expiry)
diff --git a/ocaml/tests/test_session.ml b/ocaml/tests/test_session.ml
index 518dc221d72..4b441fc325b 100644
--- a/ocaml/tests/test_session.ml
+++ b/ocaml/tests/test_session.ml
@@ -1,8 +1,8 @@
module Date = Xapi_stdext_date.Date
-let now = Date.of_string "2020-09-22T14:57:11Z"
+let now = Date.of_iso8601 "2020-09-22T14:57:11Z"
-let future = Date.of_string "2020-09-22T15:03:13Z"
+let future = Date.of_iso8601 "2020-09-22T15:03:13Z"
let fail_login ~__context ~uname ~originator ~now () =
try
diff --git a/ocaml/tests/test_updateinfo.ml b/ocaml/tests/test_updateinfo.ml
index 6df2f0b2fba..6e05875e4f1 100644
--- a/ocaml/tests/test_updateinfo.ml
+++ b/ocaml/tests/test_updateinfo.ml
@@ -430,7 +430,7 @@ let fields_of_updateinfo =
)
(list string)
; field "issued"
- (fun (r : UpdateInfo.t) -> Xapi_stdext_date.Date.to_string r.issued)
+ (fun (r : UpdateInfo.t) -> Xapi_stdext_date.Date.to_rfc3339 r.issued)
string
; field "severity"
(fun (r : UpdateInfo.t) -> Severity.to_string r.severity)
@@ -644,7 +644,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
; update_type= "security"
; livepatches= []
; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z"
; severity= Severity.High
; title= "title"
}
@@ -690,7 +690,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
; update_type= "security"
; livepatches= []
; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z"
; severity= Severity.High
; title= "title"
}
@@ -747,7 +747,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
; update_type= "security"
; livepatches= []
; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z"
; severity= Severity.High
; title= "title"
}
@@ -771,7 +771,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
; update_type= "security"
; livepatches= []
; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:50Z"
+ Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:50Z"
; severity= Severity.None
; title= "title"
}
@@ -828,7 +828,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
; update_type= "security"
; livepatches= []
; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z"
; severity= Severity.High
; title= "title"
}
@@ -852,7 +852,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
; update_type= "security"
; livepatches= []
; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:50Z"
+ Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:50Z"
; severity= Severity.None
; title= "title"
}
@@ -937,7 +937,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
; update_type= "security"
; livepatches= []
; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z"
; severity= Severity.High
; title= "title"
}
@@ -1034,7 +1034,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
; update_type= "security"
; livepatches= []
; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z"
; severity= Severity.High
; title= "title"
}
@@ -1112,7 +1112,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
}
]
; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z"
; severity= Severity.High
; title= "title"
}
@@ -1190,7 +1190,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
}
]
; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z"
; severity= Severity.High
; title= "title"
}
diff --git a/ocaml/tests/test_xapi_db_upgrade.ml b/ocaml/tests/test_xapi_db_upgrade.ml
index 6b488fec157..f14838ef6ab 100644
--- a/ocaml/tests/test_xapi_db_upgrade.ml
+++ b/ocaml/tests/test_xapi_db_upgrade.ml
@@ -38,14 +38,14 @@ let update_snapshots () =
let a = T.make_vm ~__context ~name_label:"a" () in
let a_snap = T.make_vm ~__context ~name_label:"a snap" () in
Db.VM.set_snapshot_of ~__context ~self:a_snap ~value:a ;
- Db.VM.set_snapshot_time ~__context ~self:a_snap ~value:(Date.of_float 1.) ;
+ Db.VM.set_snapshot_time ~__context ~self:a_snap ~value:(Date.of_unix_time 1.) ;
let b = T.make_vm ~__context ~name_label:"b" () in
let b_snap = T.make_vm ~__context ~name_label:"b snap" () in
Db.VM.set_snapshot_of ~__context ~self:b_snap ~value:b ;
- Db.VM.set_snapshot_time ~__context ~self:b_snap ~value:(Date.of_float 1.) ;
+ Db.VM.set_snapshot_time ~__context ~self:b_snap ~value:(Date.of_unix_time 1.) ;
let b_snap2 = T.make_vm ~__context ~name_label:"b snap2" () in
Db.VM.set_snapshot_of ~__context ~self:b_snap2 ~value:b ;
- Db.VM.set_snapshot_time ~__context ~self:b_snap2 ~value:(Date.of_float 2.) ;
+ Db.VM.set_snapshot_time ~__context ~self:b_snap2 ~value:(Date.of_unix_time 2.) ;
X.update_snapshots.fn ~__context ;
let check_vm = Alcotest.check Alcotest_comparators.(ref ()) in
(* a.parent = a_snap *)
diff --git a/ocaml/xapi-cli-server/cli_operations.ml b/ocaml/xapi-cli-server/cli_operations.ml
index 068309abaca..d0d981309da 100644
--- a/ocaml/xapi-cli-server/cli_operations.ml
+++ b/ocaml/xapi-cli-server/cli_operations.ml
@@ -1956,7 +1956,7 @@ let vdi_introduce printer rpc session_id params =
let virtual_size = 0L and physical_utilisation = 0L in
let metadata_of_pool = Ref.null in
let is_a_snapshot = false in
- let snapshot_time = Date.never in
+ let snapshot_time = Date.epoch in
let snapshot_of = Ref.null in
let vdi =
Client.VDI.introduce ~rpc ~session_id ~uuid ~name_label ~name_description
@@ -3210,7 +3210,7 @@ exception Multiple_failure of (string * string) list
let format_message msg =
Printf.sprintf "Message: time=%s priority=%Ld name='%s'"
- (Date.to_string msg.API.message_timestamp)
+ (Date.to_rfc3339 msg.API.message_timestamp)
msg.API.message_priority msg.API.message_name
let wrap_op printer pri rpc session_id op e =
@@ -3220,7 +3220,7 @@ let wrap_op printer pri rpc session_id op e =
try
Client.Message.get ~rpc ~session_id ~cls:`VM
~obj_uuid:(safe_get_field (field_lookup e.fields "uuid"))
- ~since:(Date.of_float now)
+ ~since:(Date.of_unix_time now)
with _ -> []
in
List.iter
@@ -5272,7 +5272,7 @@ let with_license_server_changes printer rpc session_id params hosts f =
current_license_servers ;
let alerts =
Client.Message.get_since ~rpc ~session_id
- ~since:(Date.of_float (now -. 1.))
+ ~since:(Date.of_unix_time (now -. 1.))
in
let print_if_checkout_error (ref, msg) =
if
@@ -6245,7 +6245,7 @@ let license_of_host rpc session_id host =
let rstr = Features.of_assoc_list params in
let expiry =
if List.mem_assoc "expiry" params then
- Date.to_float (Date.of_string (List.assoc "expiry" params))
+ Date.to_unix_time (Date.of_iso8601 (List.assoc "expiry" params))
else
0.
in
@@ -6280,7 +6280,7 @@ let diagnostic_license_status printer rpc session_id _params =
; String.sub h.uuid 0 8
; Features.to_compact_string h.rstr
; h.edition
- ; Date.to_string (Date.of_float h.expiry)
+ ; Date.to_rfc3339 (Date.of_unix_time h.expiry)
; Printf.sprintf "%.1f" ((h.expiry -. now) /. (24. *. 60. *. 60.))
]
)
diff --git a/ocaml/xapi-cli-server/records.ml b/ocaml/xapi-cli-server/records.ml
index 1e7393d377f..3798280d082 100644
--- a/ocaml/xapi-cli-server/records.ml
+++ b/ocaml/xapi-cli-server/records.ml
@@ -376,7 +376,7 @@ let message_record rpc session_id message =
~get:(fun () -> (x ()).API.message_obj_uuid)
()
; make_field ~name:"timestamp"
- ~get:(fun () -> Date.to_string (x ()).API.message_timestamp)
+ ~get:(fun () -> Date.to_rfc3339 (x ()).API.message_timestamp)
()
; make_field ~name:"body" ~get:(fun () -> (x ()).API.message_body) ()
]
@@ -749,10 +749,10 @@ let task_record rpc session_id task =
; make_field ~name:"type" ~get:(fun () -> (x ()).API.task_type) ()
; make_field ~name:"result" ~get:(fun () -> (x ()).API.task_result) ()
; make_field ~name:"created"
- ~get:(fun () -> Date.to_string (x ()).API.task_created)
+ ~get:(fun () -> Date.to_rfc3339 (x ()).API.task_created)
()
; make_field ~name:"finished"
- ~get:(fun () -> Date.to_string (x ()).API.task_finished)
+ ~get:(fun () -> Date.to_rfc3339 (x ()).API.task_finished)
()
; make_field ~name:"error_info"
~get:(fun () -> concat_with_semi (x ()).API.task_error_info)
@@ -1447,11 +1447,11 @@ let pool_record rpc session_id pool =
()
; make_field ~name:"telemetry-next-collection"
~get:(fun () ->
- (x ()).API.pool_telemetry_next_collection |> Date.to_string
+ (x ()).API.pool_telemetry_next_collection |> Date.to_rfc3339
)
()
; make_field ~name:"last-update-sync"
- ~get:(fun () -> Date.to_string (x ()).API.pool_last_update_sync)
+ ~get:(fun () -> Date.to_rfc3339 (x ()).API.pool_last_update_sync)
()
; make_field ~name:"update-sync-frequency"
~get:(fun () ->
@@ -1550,7 +1550,7 @@ let vmss_record rpc session_id vmss =
)
()
; make_field ~name:"last-run-time"
- ~get:(fun () -> Date.to_string (x ()).API.vMSS_last_run_time)
+ ~get:(fun () -> Date.to_rfc3339 (x ()).API.vMSS_last_run_time)
()
; make_field ~name:"VMs"
~get:(fun () ->
@@ -1842,7 +1842,7 @@ let vm_record rpc session_id vm =
~get:(fun () -> get_uuids_from_refs (x ()).API.vM_snapshots)
()
; make_field ~name:"snapshot-time"
- ~get:(fun () -> Date.to_string (x ()).API.vM_snapshot_time)
+ ~get:(fun () -> Date.to_rfc3339 (x ()).API.vM_snapshot_time)
()
; make_field ~name:"transportable-snapshot-id" ~hidden:true
~get:(fun () -> (x ()).API.vM_transportable_snapshot_id)
@@ -2264,14 +2264,14 @@ let vm_record rpc session_id vm =
; make_field ~name:"start-time"
~get:(fun () ->
Option.fold ~none:unknown_time
- ~some:(fun m -> Date.to_string m.API.vM_metrics_start_time)
+ ~some:(fun m -> Date.to_rfc3339 m.API.vM_metrics_start_time)
(xm ())
)
()
; make_field ~name:"install-time"
~get:(fun () ->
Option.fold ~none:unknown_time
- ~some:(fun m -> Date.to_string m.API.vM_metrics_install_time)
+ ~some:(fun m -> Date.to_rfc3339 m.API.vM_metrics_install_time)
(xm ())
)
()
@@ -2410,7 +2410,9 @@ let vm_record rpc session_id vm =
; make_field ~name:"guest-metrics-last-updated"
~get:(fun () ->
Option.fold ~none:nid
- ~some:(fun m -> Date.to_string m.API.vM_guest_metrics_last_updated)
+ ~some:(fun m ->
+ Date.to_rfc3339 m.API.vM_guest_metrics_last_updated
+ )
(xgm ())
)
()
@@ -2611,7 +2613,7 @@ let host_crashdump_record rpc session_id host =
~get:(fun () -> get_uuid_from_ref (x ()).API.host_crashdump_host)
()
; make_field ~name:"timestamp"
- ~get:(fun () -> Date.to_string (x ()).API.host_crashdump_timestamp)
+ ~get:(fun () -> Date.to_rfc3339 (x ()).API.host_crashdump_timestamp)
()
; make_field ~name:"size"
~get:(fun () -> Int64.to_string (x ()).API.host_crashdump_size)
@@ -3203,7 +3205,7 @@ let host_record rpc session_id host =
)
()
; make_field ~name:"last-software-update"
- ~get:(fun () -> Date.to_string (x ()).API.host_last_software_update)
+ ~get:(fun () -> Date.to_rfc3339 (x ()).API.host_last_software_update)
()
; make_field ~name:"latest-synced-updates-applied"
~get:(fun () ->
@@ -3274,7 +3276,7 @@ let vdi_record rpc session_id vdi =
~get:(fun () -> get_uuids_from_refs (x ()).API.vDI_snapshots)
()
; make_field ~name:"snapshot-time"
- ~get:(fun () -> Date.to_string (x ()).API.vDI_snapshot_time)
+ ~get:(fun () -> Date.to_rfc3339 (x ()).API.vDI_snapshot_time)
()
; make_field ~name:"allowed-operations"
~get:(fun () ->
@@ -5118,7 +5120,7 @@ let cluster_host_record rpc session_id cluster_host =
()
; make_field ~name:"last-update-live"
~get:(fun () ->
- (x ()).API.cluster_host_last_update_live |> Date.to_string
+ (x ()).API.cluster_host_last_update_live |> Date.to_rfc3339
)
()
; make_field ~name:"allowed-operations"
@@ -5184,10 +5186,10 @@ let certificate_record rpc session_id certificate =
~get:(fun () -> (x ()).API.certificate_host |> get_uuid_from_ref)
()
; make_field ~name:"not-before"
- ~get:(fun () -> (x ()).API.certificate_not_before |> Date.to_string)
+ ~get:(fun () -> (x ()).API.certificate_not_before |> Date.to_rfc3339)
()
; make_field ~name:"not-after"
- ~get:(fun () -> (x ()).API.certificate_not_after |> Date.to_string)
+ ~get:(fun () -> (x ()).API.certificate_not_after |> Date.to_rfc3339)
()
; make_field ~name:"fingerprint"
~get:(fun () -> (x ()).API.certificate_fingerprint)
diff --git a/ocaml/xapi-idl/storage/storage_interface.ml b/ocaml/xapi-idl/storage/storage_interface.ml
index 4b3e03e48e9..f5bd93de60b 100644
--- a/ocaml/xapi-idl/storage/storage_interface.ml
+++ b/ocaml/xapi-idl/storage/storage_interface.ml
@@ -206,8 +206,7 @@ type vdi_info = {
; (* sm_config: workaround via XenAPI *)
metadata_of_pool: string [@default ""]
; is_a_snapshot: bool [@default false]
- ; snapshot_time: string
- [@default Xapi_stdext_date.Date.to_string Xapi_stdext_date.Date.never]
+ ; snapshot_time: string [@default Xapi_stdext_date.Date.(to_rfc3339 epoch)]
; snapshot_of: Vdi.t [@default Vdi.of_string ""]
; (* managed: workaround via XenAPI *)
read_only: bool [@default false]
diff --git a/ocaml/xapi-storage-script/main.ml b/ocaml/xapi-storage-script/main.ml
index 74ea3bb8d9f..cd6575bc9b3 100644
--- a/ocaml/xapi-storage-script/main.ml
+++ b/ocaml/xapi-storage-script/main.ml
@@ -1330,9 +1330,7 @@ let bind ~volume_script_dir =
Volume_client.snapshot (volume_rpc ~dbg) dbg sr vdi
)
>>>= fun response ->
- let now =
- Xapi_stdext_date.Date.(to_string (of_float (Unix.gettimeofday ())))
- in
+ let now = Xapi_stdext_date.Date.(to_rfc3339 (now ())) in
set ~dbg ~sr ~vdi:response.Xapi_storage.Control.key
~key:_snapshot_time_key ~value:now
>>>= fun () ->
diff --git a/ocaml/xapi/certificates.ml b/ocaml/xapi/certificates.ml
index fe66194cb0e..6e1c01b7be6 100644
--- a/ocaml/xapi/certificates.ml
+++ b/ocaml/xapi/certificates.ml
@@ -214,7 +214,7 @@ end = struct
in
(name, Ref.null, `ca, remove_obsoleted_copies)
in
- let date_of_ptime time = Date.of_float (Ptime.to_float_s time) in
+ let date_of_ptime time = Date.of_unix_time (Ptime.to_float_s time) in
let dates_of_ptimes (a, b) = (date_of_ptime a, date_of_ptime b) in
let not_before, not_after =
dates_of_ptimes (X509.Certificate.validity certificate)
diff --git a/ocaml/xapi/create_misc.ml b/ocaml/xapi/create_misc.ml
index beb94f4751c..d329170fce6 100644
--- a/ocaml/xapi/create_misc.ml
+++ b/ocaml/xapi/create_misc.ml
@@ -280,7 +280,7 @@ and create_domain_zero_record ~__context ~domain_zero_ref (host_info : host_info
~scheduled_to_be_resident_on:Ref.null ~affinity:localhost
~suspend_VDI:Ref.null ~domid:0L ~domarch ~is_control_domain:true
~is_a_template:false ~is_default_template:false ~is_a_snapshot:false
- ~snapshot_time:Date.never ~snapshot_of:Ref.null
+ ~snapshot_time:Date.epoch ~snapshot_of:Ref.null
~transportable_snapshot_id:"" ~snapshot_info:[] ~snapshot_metadata:""
~parent:Ref.null ~other_config:[] ~blobs:[] ~xenstore_data:[] ~tags:[]
~user_version:1L ~ha_restart_priority:"" ~ha_always_run:false
@@ -348,8 +348,8 @@ and create_domain_zero_metrics_record ~__context ~domain_zero_metrics_ref
~memory_actual:memory_constraints.target
~vCPUs_utilisation:(List.map (fun x -> (Int64.of_int x, 0.)) (mkints vcpus))
~vCPUs_number:(Int64.of_int vcpus) ~vCPUs_CPU:[] ~vCPUs_params:[]
- ~vCPUs_flags:[] ~state:[] ~start_time:Date.never ~install_time:Date.never
- ~last_updated:Date.never ~other_config:[] ~hvm:false ~nomigrate:false
+ ~vCPUs_flags:[] ~state:[] ~start_time:Date.epoch ~install_time:Date.epoch
+ ~last_updated:Date.epoch ~other_config:[] ~hvm:false ~nomigrate:false
~nested_virt:false ~current_domain_type:Xapi_globs.domain_zero_domain_type
and update_domain_zero_record ~__context ~domain_zero_ref (host_info : host_info)
diff --git a/ocaml/xapi/db_gc_util.ml b/ocaml/xapi/db_gc_util.ml
index 182eaac00df..7972aa28ed9 100644
--- a/ocaml/xapi/db_gc_util.ml
+++ b/ocaml/xapi/db_gc_util.ml
@@ -308,14 +308,14 @@ let timeout_tasks ~__context =
let completed_old, completed_young =
List.partition
(fun (_, t) ->
- Date.to_float t.Db_actions.task_finished < oldest_completed_time
+ Date.to_unix_time t.Db_actions.task_finished < oldest_completed_time
)
completed_gcable
in
let pending_old, pending_young =
List.partition
(fun (_, t) ->
- Date.to_float t.Db_actions.task_created < oldest_pending_time
+ Date.to_unix_time t.Db_actions.task_created < oldest_pending_time
)
pending
in
@@ -360,8 +360,8 @@ let timeout_tasks ~__context =
List.sort
(fun (_, t1) (_, t2) ->
compare
- (Date.to_float t1.Db_actions.task_finished)
- (Date.to_float t2.Db_actions.task_finished)
+ (Date.to_unix_time t1.Db_actions.task_finished)
+ (Date.to_unix_time t2.Db_actions.task_finished)
)
completed
in
@@ -422,7 +422,7 @@ let timeout_sessions_common ~__context sessions limit session_group =
List.map
(fun (x, y) ->
( x
- , Date.to_float y.Db_actions.session_last_active
+ , Date.to_unix_time y.Db_actions.session_last_active
, y.Db_actions.session_uuid
)
)
@@ -447,7 +447,7 @@ let timeout_sessions_common ~__context sessions limit session_group =
debug "Session.destroy _ref=%s uuid=%s %s (last active %s): %s"
(Ref.string_of s) uuid
(Context.trackid_of_session (Some s))
- (Date.to_string (Date.of_float active))
+ (Date.to_rfc3339 (Date.of_unix_time active))
doc ;
Xapi_session.destroy_db_session ~__context ~self:s
)
@@ -586,7 +586,7 @@ let timeout_alerts ~__context =
let all_alerts = Db.Alert.get_all ~__context in
let now = Unix.gettimeofday() in
List.iter (fun alert ->
- let alert_time = Date.to_float (Db.Alert.get_timestamp ~__context ~self:alert) in
+ let alert_time = Date.to_unix_time (Db.Alert.get_timestamp ~__context ~self:alert) in
if now -. alert_time > Xapi_globs.alert_timeout then
Db.Alert.destroy ~__context ~self:alert
) all_alerts
diff --git a/ocaml/xapi/dbsync.ml b/ocaml/xapi/dbsync.ml
index 5ee30bb39c8..875b406bb89 100644
--- a/ocaml/xapi/dbsync.ml
+++ b/ocaml/xapi/dbsync.ml
@@ -42,7 +42,7 @@ let create_host_metrics ~__context =
Db.Host_metrics.create ~__context ~ref:r
~uuid:(Uuidx.to_string (Uuidx.make ()))
~live:false ~memory_total:0L ~memory_free:0L
- ~last_updated:Xapi_stdext_date.Date.never ~other_config:[] ;
+ ~last_updated:Xapi_stdext_date.Date.epoch ~other_config:[] ;
Db.Host.set_metrics ~__context ~self ~value:r
)
)
diff --git a/ocaml/xapi/dbsync_master.ml b/ocaml/xapi/dbsync_master.ml
index 8f8e6a582f8..31f235e7214 100644
--- a/ocaml/xapi/dbsync_master.ml
+++ b/ocaml/xapi/dbsync_master.ml
@@ -291,11 +291,10 @@ let ensure_vm_metrics_records_exist __context =
let uuid = Uuidx.to_string (Uuidx.make ()) in
Db.VM_metrics.create ~__context ~ref:m ~uuid ~vCPUs_number:0L
~vCPUs_utilisation:[] ~memory_actual:0L ~vCPUs_CPU:[] ~vCPUs_params:[]
- ~vCPUs_flags:[] ~start_time:Xapi_stdext_date.Date.never
- ~install_time:Xapi_stdext_date.Date.never ~state:[]
- ~last_updated:(Xapi_stdext_date.Date.of_float 0.)
- ~other_config:[] ~hvm:false ~nested_virt:false ~nomigrate:false
- ~current_domain_type:`unspecified ;
+ ~vCPUs_flags:[] ~start_time:Xapi_stdext_date.Date.epoch
+ ~install_time:Xapi_stdext_date.Date.epoch ~state:[]
+ ~last_updated:Xapi_stdext_date.Date.epoch ~other_config:[] ~hvm:false
+ ~nested_virt:false ~nomigrate:false ~current_domain_type:`unspecified ;
Db.VM.set_metrics ~__context ~self:vm ~value:m
)
)
diff --git a/ocaml/xapi/dbsync_slave.ml b/ocaml/xapi/dbsync_slave.ml
index 32ee7d44d21..3b90a3a05c3 100644
--- a/ocaml/xapi/dbsync_slave.ml
+++ b/ocaml/xapi/dbsync_slave.ml
@@ -73,12 +73,12 @@ let get_start_time () =
let uptime = String.split ' ' uptime in
let uptime = List.hd uptime in
let uptime = float_of_string uptime in
- let boot_time = Date.of_float (now -. uptime) in
- debug " system booted at %s" (Date.to_string boot_time) ;
+ let boot_time = Date.of_unix_time (now -. uptime) in
+ debug " system booted at %s" (Date.to_rfc3339 boot_time) ;
boot_time
with e ->
debug "Calculating boot time failed with '%s'" (ExnHelper.string_of_exn e) ;
- Date.never
+ Date.epoch
(* not sufficient just to fill in this data on create time [Xen caps may change if VT enabled in BIOS etc.] *)
@@ -106,7 +106,9 @@ let refresh_localhost_info ~__context info =
Db.Host.set_capabilities ~__context ~self:host ~value:caps ;
Db.Host.set_address ~__context ~self:host ~value:(get_my_ip_addr ~__context) ;
let boot_time_key = "boot_time" in
- let boot_time_value = string_of_float (Date.to_float (get_start_time ())) in
+ let boot_time_value =
+ string_of_float (Date.to_unix_time (get_start_time ()))
+ in
Db.Host.remove_from_other_config ~__context ~self:host ~key:boot_time_key ;
Db.Host.add_to_other_config ~__context ~self:host ~key:boot_time_key
~value:boot_time_value ;
diff --git a/ocaml/xapi/debug_populate.ml b/ocaml/xapi/debug_populate.ml
index 0eb1a89581a..3c192509915 100644
--- a/ocaml/xapi/debug_populate.ml
+++ b/ocaml/xapi/debug_populate.ml
@@ -72,7 +72,7 @@ let rec make_vdis_and_vbds __context vmref i =
let physical_utilisation = 1L in
let metadata_of_pool = Ref.null in
let is_a_snapshot = false in
- let snapshot_time = Xapi_stdext_date.Date.never in
+ let snapshot_time = Xapi_stdext_date.Date.epoch in
let snapshot_of = Ref.null in
let sharable = false in
let cbt_enabled = false in
diff --git a/ocaml/xapi/export.ml b/ocaml/xapi/export.ml
index 24589827bc8..a81ec647225 100644
--- a/ocaml/xapi/export.ml
+++ b/ocaml/xapi/export.ml
@@ -241,7 +241,7 @@ let make_vm ?(with_snapshot_metadata = false) ~preserve_power_state table
; API.vM_snapshots=
(if with_snapshot_metadata then vm.API.vM_snapshots else [])
; API.vM_snapshot_time=
- (if with_snapshot_metadata then vm.API.vM_snapshot_time else Date.never)
+ (if with_snapshot_metadata then vm.API.vM_snapshot_time else Date.epoch)
; API.vM_transportable_snapshot_id=
( if with_snapshot_metadata then
vm.API.vM_transportable_snapshot_id
diff --git a/ocaml/xapi/license_check.ml b/ocaml/xapi/license_check.ml
index d34f2bd4526..e6df516f353 100644
--- a/ocaml/xapi/license_check.ml
+++ b/ocaml/xapi/license_check.ml
@@ -20,7 +20,7 @@ let never, _ =
let get_expiry_date ~__context ~host =
let license = Db.Host.get_license_params ~__context ~self:host in
if List.mem_assoc "expiry" license then
- Some (Xapi_stdext_date.Date.of_string (List.assoc "expiry" license))
+ Some (Xapi_stdext_date.Date.of_iso8601 (List.assoc "expiry" license))
else
None
@@ -30,7 +30,7 @@ let check_expiry ~__context ~host =
| None ->
false (* No expiry date means no expiry :) *)
| Some date ->
- Unix.time () > Xapi_stdext_date.Date.to_float date
+ Unix.time () > Xapi_stdext_date.Date.to_unix_time date
in
if expired then
raise (Api_errors.Server_error (Api_errors.license_expired, []))
diff --git a/ocaml/xapi/license_check.mli b/ocaml/xapi/license_check.mli
index f970ff878df..610faaf9e0b 100644
--- a/ocaml/xapi/license_check.mli
+++ b/ocaml/xapi/license_check.mli
@@ -20,9 +20,7 @@ val never : float
(** The expiry date that is considered to be "never". *)
val get_expiry_date :
- __context:Context.t
- -> host:API.ref_host
- -> Xapi_stdext_date.Date.iso8601 option
+ __context:Context.t -> host:API.ref_host -> Xapi_stdext_date.Date.t option
(** Returns (Some date) if the host's license has an expiry date,
* otherwise returns None. *)
diff --git a/ocaml/xapi/message_forwarding.ml b/ocaml/xapi/message_forwarding.ml
index 6ed0bc04d85..83d4ff26e24 100644
--- a/ocaml/xapi/message_forwarding.ml
+++ b/ocaml/xapi/message_forwarding.ml
@@ -1131,7 +1131,7 @@ functor
let set_telemetry_next_collection ~__context ~self ~value =
info "%s: pool='%s' value='%s'" __FUNCTION__
(pool_uuid ~__context self)
- (Xapi_stdext_date.Date.to_string value) ;
+ (Xapi_stdext_date.Date.to_rfc3339 value) ;
Local.Pool.set_telemetry_next_collection ~__context ~self ~value
let reset_telemetry_uuid ~__context ~self =
diff --git a/ocaml/xapi/monitor_master.ml b/ocaml/xapi/monitor_master.ml
index bb4e6cf2e5b..ffad86ccd6c 100644
--- a/ocaml/xapi/monitor_master.ml
+++ b/ocaml/xapi/monitor_master.ml
@@ -70,8 +70,7 @@ let set_pif_metrics ~__context ~self ~vendor ~device ~carrier ~speed ~duplex
Db.PIF_metrics.set_duplex ~__context ~self ~value:duplex ;
if pmr.API.pIF_metrics_pci_bus_path <> pcibuspath then
Db.PIF_metrics.set_pci_bus_path ~__context ~self ~value:pcibuspath ;
- Db.PIF_metrics.set_last_updated ~__context ~self
- ~value:(Date.of_float (Unix.gettimeofday ()))
+ Db.PIF_metrics.set_last_updated ~__context ~self ~value:(Date.now ())
(* Note that the following function is actually called on the slave most of the
* time now but only when the PIF information changes. *)
@@ -190,8 +189,8 @@ let update_pifs ~__context host pifs =
~uuid:(Uuidx.to_string (Uuidx.make ()))
~carrier:false ~device_name:"" ~vendor_name:"" ~device_id:""
~vendor_id:"" ~speed:0L ~duplex:false ~pci_bus_path:""
- ~io_read_kbs:0. ~io_write_kbs:0.
- ~last_updated:(Date.of_float 0.) ~other_config:[] ;
+ ~io_read_kbs:0. ~io_write_kbs:0. ~last_updated:Date.epoch
+ ~other_config:[] ;
Db.PIF.set_metrics ~__context ~self:pifdev ~value:ref ;
ref
in
diff --git a/ocaml/xapi/pool_periodic_update_sync.ml b/ocaml/xapi/pool_periodic_update_sync.ml
index 5f1e502b2b4..45aacf82a9c 100644
--- a/ocaml/xapi/pool_periodic_update_sync.ml
+++ b/ocaml/xapi/pool_periodic_update_sync.ml
@@ -144,7 +144,7 @@ let rec update_sync () =
with e ->
let exc = Printexc.to_string e in
warn "Periodic update sync failed with exception %s" exc ;
- let now = Xapi_stdext_date.Date.(now () |> to_string) in
+ let now = Xapi_stdext_date.Date.(now () |> to_rfc3339) in
let body =
Printf.sprintf
"Periodic update sync \
diff --git a/ocaml/xapi/storage_smapiv1.ml b/ocaml/xapi/storage_smapiv1.ml
index 465b5d354b1..d8bf2cdc203 100644
--- a/ocaml/xapi/storage_smapiv1.ml
+++ b/ocaml/xapi/storage_smapiv1.ml
@@ -86,7 +86,7 @@ let vdi_info_of_vdi_rec __context vdi_rec =
; ty= Storage_utils.string_of_vdi_type vdi_rec.API.vDI_type
; metadata_of_pool= Ref.string_of vdi_rec.API.vDI_metadata_of_pool
; is_a_snapshot= vdi_rec.API.vDI_is_a_snapshot
- ; snapshot_time= Date.to_string vdi_rec.API.vDI_snapshot_time
+ ; snapshot_time= Date.to_rfc3339 vdi_rec.API.vDI_snapshot_time
; snapshot_of=
( if Db.is_valid_ref __context vdi_rec.API.vDI_snapshot_of then
Db.VDI.get_uuid ~__context ~self:vdi_rec.API.vDI_snapshot_of
@@ -146,7 +146,7 @@ module SMAPIv1 : Server_impl = struct
Server_helpers.exec_with_new_task "VDI.set_snapshot_time"
~subtask_of:(Ref.of_string dbg) (fun __context ->
let vdi, _ = find_vdi ~__context sr vdi in
- let snapshot_time = Date.of_string snapshot_time in
+ let snapshot_time = Date.of_iso8601 snapshot_time in
Db.VDI.set_snapshot_time ~__context ~self:vdi ~value:snapshot_time
)
@@ -761,7 +761,7 @@ module SMAPIv1 : Server_impl = struct
(Db.VDI.get_other_config ~__context ~self:clonee)
with _ -> Uuidx.(to_string (make ()))
in
- let snapshot_time = Date.of_float (Unix.gettimeofday ()) in
+ let snapshot_time = Date.now () in
Db.VDI.set_name_label ~__context ~self ~value:vdi_info.name_label ;
Db.VDI.set_name_description ~__context ~self
~value:vdi_info.name_description ;
diff --git a/ocaml/xapi/storage_smapiv1_wrapper.ml b/ocaml/xapi/storage_smapiv1_wrapper.ml
index 2efa9194168..7c5a6a97f43 100644
--- a/ocaml/xapi/storage_smapiv1_wrapper.ml
+++ b/ocaml/xapi/storage_smapiv1_wrapper.ml
@@ -90,7 +90,7 @@ let host_state_path = ref "/var/run/nonpersistent/xapi/storage.db"
let indent x = " " ^ x
-let string_of_date x = Date.to_string (Date.of_float x)
+let string_of_date x = Date.to_rfc3339 (Date.of_unix_time x)
let with_dbg ~name ~dbg f =
Debug_info.with_dbg ~with_thread:true ~module_name:"SMAPIv1-Wrapper" ~name
diff --git a/ocaml/xapi/taskHelper.ml b/ocaml/xapi/taskHelper.ml
index 1f1d4fd7744..27e30ce3d39 100644
--- a/ocaml/xapi/taskHelper.ml
+++ b/ocaml/xapi/taskHelper.ml
@@ -44,7 +44,7 @@ let make ~__context ~http_other_config ?(description = "") ?session_id
in
let (_ : unit) =
Db_actions.DB_Action.Task.create ~ref ~__context ~created:(Date.now ())
- ~finished:(Date.of_float 0.0) ~current_operations:[] ~_type:""
+ ~finished:Date.epoch ~current_operations:[] ~_type:""
~session:(Option.value ~default:Ref.null session_id)
~resident_on:!Xapi_globs.localhost_ref ~status:`pending ~result:""
~progress:0. ~error_info:[] ~allowed_operations:[]
diff --git a/ocaml/xapi/updateinfo.ml b/ocaml/xapi/updateinfo.ml
index 375604cfe78..88e4a0cf0fc 100644
--- a/ocaml/xapi/updateinfo.ml
+++ b/ocaml/xapi/updateinfo.ml
@@ -562,7 +562,7 @@ module UpdateInfo = struct
; ("special-info", `String ui.spec_info)
; ("URL", `String ui.url)
; ("type", `String ui.update_type)
- ; ("issued", `String (Xapi_stdext_date.Date.to_string ui.issued))
+ ; ("issued", `String (Xapi_stdext_date.Date.to_rfc3339 ui.issued))
; ("severity", `String (Severity.to_string ui.severity))
; ( "livepatches"
, `List (List.map (fun x -> LivePatch.to_json x) ui.livepatches)
@@ -656,7 +656,7 @@ module UpdateInfo = struct
match List.assoc_opt "date" attrs with
| Some date -> (
try
- Xapi_stdext_date.Date.of_string
+ Xapi_stdext_date.Date.of_iso8601
(Scanf.sscanf date
"%04d-%02d-%02d %02d:%02d:%02d"
(fun y mon d h m s ->
diff --git a/ocaml/xapi/vpx.ml b/ocaml/xapi/vpx.ml
index a1cd5924987..2871ad6486f 100644
--- a/ocaml/xapi/vpx.ml
+++ b/ocaml/xapi/vpx.ml
@@ -27,7 +27,7 @@ type jobInfo = {
; importInfo: importInfo
}
-type dateTime = Xapi_stdext_date.Date.iso8601
+type dateTime = Xapi_stdext_date.Date.t
type jobInstance = {
id: string
@@ -221,12 +221,12 @@ let serverInfo_of_rpc r =
}
}
-let rpc_of_dateTime v = Rpc.DateTime (Xapi_stdext_date.Date.to_string v)
+let rpc_of_dateTime v = Rpc.DateTime (Xapi_stdext_date.Date.to_rfc3339 v)
let dateTime_of_rpc r =
match r with
| Rpc.DateTime v ->
- Xapi_stdext_date.Date.of_string v
+ Xapi_stdext_date.Date.of_iso8601 v
| x ->
rpc_type_error x "DateTime" "DateTime(datetime)"
diff --git a/ocaml/xapi/xapi_blob.ml b/ocaml/xapi/xapi_blob.ml
index 6be9cdd9abd..f483f8d7835 100644
--- a/ocaml/xapi/xapi_blob.ml
+++ b/ocaml/xapi/xapi_blob.ml
@@ -24,7 +24,7 @@ let create ~__context ~mime_type ~public =
if mime_type = "" then "application/octet-stream" else mime_type
in
Db.Blob.create ~__context ~ref ~uuid:(Uuidx.to_string uuid) ~public
- ~mime_type:mime_type' ~size:0L ~last_updated:Xapi_stdext_date.Date.never
+ ~mime_type:mime_type' ~size:0L ~last_updated:Xapi_stdext_date.Date.epoch
~name_label:"" ~name_description:"" ;
ref
@@ -212,7 +212,7 @@ let handler (req : Http.Request.t) s _ =
in
Db.Blob.set_size ~__context ~self ~value:size ;
Db.Blob.set_last_updated ~__context ~self
- ~value:(Xapi_stdext_date.Date.of_float (Unix.gettimeofday ()))
+ ~value:(Xapi_stdext_date.Date.of_unix_time (Unix.gettimeofday ()))
| _ ->
failwith "Unsupported method for BLOB"
in
diff --git a/ocaml/xapi/xapi_guest_agent.ml b/ocaml/xapi/xapi_guest_agent.ml
index ffde9e7bf77..bd13e808ec8 100644
--- a/ocaml/xapi/xapi_guest_agent.ml
+++ b/ocaml/xapi/xapi_guest_agent.ml
@@ -329,7 +329,7 @@ let create_and_set_guest_metrics (lookup : string -> string option)
~pV_drivers_version:initial_gm.pv_drivers_version
~pV_drivers_up_to_date:pV_drivers_detected ~memory:[] ~disks:[]
~networks:initial_gm.networks ~pV_drivers_detected ~other:initial_gm.other
- ~last_updated:(Date.of_float initial_gm.last_updated)
+ ~last_updated:(Date.of_unix_time initial_gm.last_updated)
~other_config:[] ~live:true
~can_use_hotplug_vbd:initial_gm.can_use_hotplug_vbd
~can_use_hotplug_vif:initial_gm.can_use_hotplug_vif ;
@@ -469,7 +469,7 @@ let all (lookup : string -> string option) (list : string -> string list)
(* if(guest_metrics_cached.memory <> memory) then
Db.VM_guest_metrics.set_memory ~__context ~self:gm ~value:memory; *)
Db.VM_guest_metrics.set_last_updated ~__context ~self:gm
- ~value:(Date.of_float last_updated) ;
+ ~value:(Date.of_unix_time last_updated) ;
if guest_metrics_cached.device_id <> device_id then
if List.mem_assoc Xapi_globs.device_id_key_name device_id then (
let value = List.assoc Xapi_globs.device_id_key_name device_id in
diff --git a/ocaml/xapi/xapi_ha.ml b/ocaml/xapi/xapi_ha.ml
index 578788f8c9c..ddfbc357fb2 100644
--- a/ocaml/xapi/xapi_ha.ml
+++ b/ocaml/xapi/xapi_ha.ml
@@ -1463,7 +1463,7 @@ let rec propose_new_master_internal ~__context ~address ~manual =
(Printf.sprintf
"Already agreed to commit host address '%s' at %s ('%f' secs ago)"
x
- (Date.to_string (Date.of_float !proposed_master_time))
+ (Date.to_rfc3339 (Date.of_unix_time !proposed_master_time))
diff
)
| None ->
diff --git a/ocaml/xapi/xapi_host.ml b/ocaml/xapi/xapi_host.ml
index 897e8572e13..aa2f07e2fba 100644
--- a/ocaml/xapi/xapi_host.ml
+++ b/ocaml/xapi/xapi_host.ml
@@ -43,7 +43,7 @@ let take n xs =
in
loop n [] xs
-let get_servertime ~__context ~host:_ = Date.of_float (Unix.gettimeofday ())
+let get_servertime ~__context ~host:_ = Date.now ()
let get_server_localtime ~__context ~host:_ = Date.localtime ()
@@ -1009,7 +1009,7 @@ let create ~__context ~uuid ~name_label ~name_description:_ ~hostname ~address
let make_new_metrics_object ref =
Db.Host_metrics.create ~__context ~ref
~uuid:(Uuidx.to_string (Uuidx.make ()))
- ~live:false ~memory_total:0L ~memory_free:0L ~last_updated:Date.never
+ ~live:false ~memory_total:0L ~memory_free:0L ~last_updated:Date.epoch
~other_config:[]
in
let name_description = "Default install" and host = Ref.make () in
@@ -1058,8 +1058,7 @@ let create ~__context ~uuid ~name_label ~name_description:_ ~hostname ~address
~latest_synced_updates_applied:`unknown ~pending_guidances_recommended:[]
~pending_guidances_full:[] ~last_update_hash:"" ;
(* If the host we're creating is us, make sure its set to live *)
- Db.Host_metrics.set_last_updated ~__context ~self:metrics
- ~value:(Date.of_float (Unix.gettimeofday ())) ;
+ Db.Host_metrics.set_last_updated ~__context ~self:metrics ~value:(Date.now ()) ;
Db.Host_metrics.set_live ~__context ~self:metrics ~value:host_is_us ;
host
diff --git a/ocaml/xapi/xapi_host.mli b/ocaml/xapi/xapi_host.mli
index 0b61af641a2..8813f037b19 100644
--- a/ocaml/xapi/xapi_host.mli
+++ b/ocaml/xapi/xapi_host.mli
@@ -272,10 +272,9 @@ val sync_data : __context:Context.t -> host:API.ref_host -> unit
val backup_rrds : __context:Context.t -> host:'b -> delay:float -> unit
-val get_servertime : __context:'a -> host:'b -> Xapi_stdext_date.Date.iso8601
+val get_servertime : __context:'a -> host:'b -> Xapi_stdext_date.Date.t
-val get_server_localtime :
- __context:'a -> host:'b -> Xapi_stdext_date.Date.iso8601
+val get_server_localtime : __context:'a -> host:'b -> Xapi_stdext_date.Date.t
val enable_binary_storage : __context:Context.t -> host:[`host] Ref.t -> unit
diff --git a/ocaml/xapi/xapi_host_crashdump.ml b/ocaml/xapi/xapi_host_crashdump.ml
index f16255e2c97..e8095ba6259 100644
--- a/ocaml/xapi/xapi_host_crashdump.ml
+++ b/ocaml/xapi/xapi_host_crashdump.ml
@@ -134,7 +134,7 @@ let resynchronise ~__context ~host =
with _ ->
(Unix.stat (Filename.concat crash_dir filename)).Unix.st_ctime
in
- let timestamp = Date.of_float timestamp in
+ let timestamp = Date.of_unix_time timestamp in
let r = Ref.make () and uuid = Uuidx.to_string (Uuidx.make ()) in
Db.Host_crashdump.create ~__context ~ref:r ~uuid ~other_config:[] ~host
~timestamp ~size ~filename
diff --git a/ocaml/xapi/xapi_local_session.ml b/ocaml/xapi/xapi_local_session.ml
index 148c776ca2f..7a5cf5f5070 100644
--- a/ocaml/xapi/xapi_local_session.ml
+++ b/ocaml/xapi/xapi_local_session.ml
@@ -14,11 +14,7 @@
(** Code to handle local sessions, used so that slaves can communicate even when
the master is down. *)
-type t = {
- r: API.ref_session
- ; pool: bool
- ; last_active: Xapi_stdext_date.Date.iso8601
-}
+type t = {r: API.ref_session; pool: bool; last_active: Xapi_stdext_date.Date.t}
let with_lock = Xapi_stdext_threads.Threadext.Mutex.execute
@@ -31,13 +27,7 @@ let get_all ~__context =
let create ~__context ~pool =
let r = Ref.make () in
- let session =
- {
- r
- ; pool
- ; last_active= Xapi_stdext_date.Date.of_float (Unix.gettimeofday ())
- }
- in
+ let session = {r; pool; last_active= Xapi_stdext_date.Date.now ()} in
with_lock m (fun () -> Hashtbl.replace table r session) ;
r
diff --git a/ocaml/xapi/xapi_local_session.mli b/ocaml/xapi/xapi_local_session.mli
index dbba9a57a8b..c7859879990 100644
--- a/ocaml/xapi/xapi_local_session.mli
+++ b/ocaml/xapi/xapi_local_session.mli
@@ -13,11 +13,7 @@
*)
(** Represents local sessions, for use in emergency mode *)
-type t = {
- r: API.ref_session
- ; pool: bool
- ; last_active: Xapi_stdext_date.Date.iso8601
-}
+type t = {r: API.ref_session; pool: bool; last_active: Xapi_stdext_date.Date.t}
val get_all : __context:Context.t -> API.ref_session list
diff --git a/ocaml/xapi/xapi_message.ml b/ocaml/xapi/xapi_message.ml
index 8d81bef3777..8bc43cc48e8 100644
--- a/ocaml/xapi/xapi_message.ml
+++ b/ocaml/xapi/xapi_message.ml
@@ -73,7 +73,7 @@ let to_xml output _ref gen message =
; tag "priority" [data (Int64.to_string message.API.message_priority)]
; tag "cls" [data (Record_util.cls_to_string message.API.message_cls)]
; tag "obj_uuid" [data message.API.message_obj_uuid]
- ; tag "timestamp" [data (Date.to_string message.API.message_timestamp)]
+ ; tag "timestamp" [data (Date.to_rfc3339 message.API.message_timestamp)]
; tag "uuid" [data message.API.message_uuid]
; tag "body" [data message.API.message_body]
]
@@ -96,7 +96,7 @@ let of_xml input =
; API.message_priority= 0L
; API.message_cls= `VM
; API.message_obj_uuid= ""
- ; API.message_timestamp= Date.never
+ ; API.message_timestamp= Date.epoch
; API.message_body= ""
; API.message_uuid= ""
}
@@ -123,7 +123,8 @@ let of_xml input =
| "obj_uuid" ->
message := {!message with API.message_obj_uuid= dat}
| "timestamp" ->
- message := {!message with API.message_timestamp= Date.of_string dat}
+ message :=
+ {!message with API.message_timestamp= Date.of_iso8601 dat}
| "uuid" ->
message := {!message with API.message_uuid= dat}
| "body" ->
@@ -342,7 +343,7 @@ let write ~__context ~_ref ~message =
)
) ;
Unixext.mkdir_rec message_dir 0o700 ;
- let timestamp = ref (Date.to_float message.API.message_timestamp) in
+ let timestamp = ref (Date.to_unix_time message.API.message_timestamp) in
if message_exists () then
Some (message_gen ())
else
@@ -442,7 +443,7 @@ let create ~__context ~name ~priority ~cls ~obj_uuid ~body =
; API.message_priority= priority
; API.message_cls= cls
; API.message_obj_uuid= obj_uuid
- ; API.message_timestamp= Date.of_float timestamp
+ ; API.message_timestamp= Date.of_unix_time timestamp
; API.message_body= body
}
in
@@ -596,8 +597,8 @@ let get_real_inner dir filter name_filter =
r
else
compare
- (Date.to_float m2.API.message_timestamp)
- (Date.to_float m1.API.message_timestamp)
+ (Date.to_unix_time m2.API.message_timestamp)
+ (Date.to_unix_time m1.API.message_timestamp)
)
messages
with _ -> []
@@ -631,16 +632,16 @@ let get ~__context ~cls ~obj_uuid ~since =
(* Read in all the messages for a particular object *)
let class_symlink = class_symlink cls obj_uuid in
if not (check_uuid ~__context ~cls ~uuid:obj_uuid) then
- raise (Api_errors.Server_error (Api_errors.uuid_invalid, [])) ;
+ raise Api_errors.(Server_error (uuid_invalid, [])) ;
let msg =
get_real_inner class_symlink
- (fun msg -> Date.to_float msg.API.message_timestamp > Date.to_float since)
+ (fun msg -> Date.is_later msg.API.message_timestamp ~than:since)
(fun _ -> true)
in
List.map (fun (_, b, c) -> (b, c)) msg
let get_since ~__context ~since =
- get_real message_dir (fun _ -> true) (Date.to_float since)
+ get_real message_dir (fun _ -> true) (Date.to_unix_time since)
let get_since_for_events ~__context since =
let cached_result =
@@ -747,7 +748,7 @@ let repopulate_cache () =
let last_256 = Listext.List.take 256 messages in
in_memory_cache := last_256 ;
let get_ts (ts, _, m) =
- Printf.sprintf "%Ld (%s)" ts (Date.to_string m.API.message_timestamp)
+ Printf.sprintf "%Ld (%s)" ts (Date.to_rfc3339 m.API.message_timestamp)
in
debug "Constructing in-memory-cache: most length=%d" (List.length last_256) ;
( try
diff --git a/ocaml/xapi/xapi_pif.ml b/ocaml/xapi/xapi_pif.ml
index b6067a509de..56dff779240 100644
--- a/ocaml/xapi/xapi_pif.ml
+++ b/ocaml/xapi/xapi_pif.ml
@@ -412,7 +412,7 @@ let make_pif_metrics ~__context =
Db.PIF_metrics.create ~__context ~ref:metrics ~uuid:metrics_uuid
~carrier:false ~device_name:"" ~vendor_name:"" ~device_id:"" ~vendor_id:""
~speed:0L ~duplex:false ~pci_bus_path:"" ~io_read_kbs:0. ~io_write_kbs:0.
- ~last_updated:(Date.of_float 0.) ~other_config:[]
+ ~last_updated:Date.epoch ~other_config:[]
in
metrics
diff --git a/ocaml/xapi/xapi_pool.ml b/ocaml/xapi/xapi_pool.ml
index 4fdefa0f8fb..49ea7194dc9 100644
--- a/ocaml/xapi/xapi_pool.ml
+++ b/ocaml/xapi/xapi_pool.ml
@@ -3127,10 +3127,10 @@ let get_license_state ~__context ~self:_ =
| None ->
"never"
| Some date ->
- if date = Date.of_float License_check.never then
+ if date = Date.of_unix_time License_check.never then
"never"
else
- Date.to_string date
+ Date.to_rfc3339 date
in
[("edition", pool_edition); ("expiry", pool_expiry)]
@@ -3285,7 +3285,7 @@ let alert_failed_login_attempts () =
let now = Date.localtime () in
let login_failures_between =
Printf.sprintf "login failures between '%s' and last check"
- (Date.to_string now)
+ (Date.to_rfc3339 now)
in
match Xapi_session.get_failed_login_stats () with
| None ->
@@ -3678,7 +3678,7 @@ let set_telemetry_next_collection ~__context ~self ~value =
let err_msg = "Can't parse date and time for telemetry collection." in
raise Api_errors.(Server_error (internal_error, [err_msg]))
in
- let ts = Date.to_string value in
+ let ts = Date.to_rfc3339 value in
match Ptime.is_later dt_of_value ~than:dt_of_max_sched with
| true ->
raise Api_errors.(Server_error (telemetry_next_collection_too_late, [ts]))
diff --git a/ocaml/xapi/xapi_pool.mli b/ocaml/xapi/xapi_pool.mli
index 5fc33c66cad..9e74ea3f373 100644
--- a/ocaml/xapi/xapi_pool.mli
+++ b/ocaml/xapi/xapi_pool.mli
@@ -397,7 +397,7 @@ val set_https_only :
val set_telemetry_next_collection :
__context:Context.t
-> self:API.ref_pool
- -> value:Xapi_stdext_date.Date.iso8601
+ -> value:Xapi_stdext_date.Date.t
-> unit
val reset_telemetry_uuid : __context:Context.t -> self:API.ref_pool -> unit
diff --git a/ocaml/xapi/xapi_pool_license.ml b/ocaml/xapi/xapi_pool_license.ml
index 5e69d64dee1..a37805127db 100644
--- a/ocaml/xapi/xapi_pool_license.ml
+++ b/ocaml/xapi/xapi_pool_license.ml
@@ -17,8 +17,8 @@ module D = Debug.Make (struct let name = "xapi_pool_license" end)
open D
(* Compare two date options, where None is always greater than (Some _) *)
-let compare_dates (a : Xapi_stdext_date.Date.iso8601 option)
- (b : Xapi_stdext_date.Date.iso8601 option) =
+let compare_dates (a : Xapi_stdext_date.Date.t option)
+ (b : Xapi_stdext_date.Date.t option) =
match (a, b) with
| None, None ->
0
diff --git a/ocaml/xapi/xapi_pool_patch.ml b/ocaml/xapi/xapi_pool_patch.ml
index 5988a1abc7c..72033070bc5 100644
--- a/ocaml/xapi/xapi_pool_patch.ml
+++ b/ocaml/xapi/xapi_pool_patch.ml
@@ -140,7 +140,7 @@ let get_patch_applied_to ~__context ~patch ~host =
let write_patch_applied_db ~__context ?date ?(applied = true) ~self ~host () =
let date =
- Xapi_stdext_date.Date.of_float
+ Xapi_stdext_date.Date.of_unix_time
(match date with Some d -> d | None -> Unix.gettimeofday ())
in
match get_patch_applied_to ~__context ~patch:self ~host with
diff --git a/ocaml/xapi/xapi_session.ml b/ocaml/xapi/xapi_session.ml
index 43564278dda..72a0ff7c705 100644
--- a/ocaml/xapi/xapi_session.ml
+++ b/ocaml/xapi/xapi_session.ml
@@ -41,7 +41,7 @@ module AuthFail : sig
val on_fail :
__context:Context.t
- -> now:Date.iso8601
+ -> now:Date.t
-> uname:string option
-> originator:string option
-> record:[< `log_only | `log_and_alert]
@@ -85,7 +85,7 @@ end = struct
type client_failed_attempts = {
client: client
; num_failed_attempts: int
- ; last_failed_attempt: Date.iso8601
+ ; last_failed_attempt: Date.t
}
let up_to_3 xs x =
@@ -103,7 +103,7 @@ end = struct
|}
(string_of_client x.client)
x.num_failed_attempts
- (Date.to_string x.last_failed_attempt)
+ (Date.to_rfc3339 x.last_failed_attempt)
type stats = {
total_num_failed_attempts: int
@@ -143,7 +143,7 @@ end = struct
val get : unit -> stats option
(* returns the number of failures from this client since last call to [ get ] *)
- val record_client : client -> now:Date.iso8601 -> int
+ val record_client : client -> now:Date.t -> int
(* returns number of failures from unknown clients since last call to [ get ] *)
val record_unknown : unit -> int
@@ -159,7 +159,7 @@ end = struct
ctr
)
- type value = {num_failed_attempts: int; last_failed_attempt: Date.iso8601}
+ type value = {num_failed_attempts: int; last_failed_attempt: Date.t}
let table = Hashtbl.create 10
@@ -247,7 +247,7 @@ let _record_login_failure ~__context ~now ~uname ~originator ~record f =
let record_login_failure ~__context ~uname ~originator ~record f =
Context.with_tracing ?originator ~__context __FUNCTION__ @@ fun __context ->
- let now = Unix.time () |> Date.of_float in
+ let now = Date.now () in
_record_login_failure ~__context ~now ~uname ~originator ~record f
let get_failed_login_stats = AuthFail.get_stats_string
@@ -448,11 +448,12 @@ let revalidate_external_session ~__context ~session =
(* 2. has the external session expired/does it need revalidation? *)
let session_last_validation_time =
- Date.to_float (Db.Session.get_validation_time ~__context ~self:session)
+ Date.to_unix_time
+ (Db.Session.get_validation_time ~__context ~self:session)
in
- let now = Unix.time () in
+ let now = Date.now () in
let session_needs_revalidation =
- now
+ Date.to_unix_time now
> session_last_validation_time +. session_lifespan +. random_lifespan
in
if session_needs_revalidation then (
@@ -528,7 +529,7 @@ let revalidate_external_session ~__context ~session =
(* session passed revalidation, let's update its last revalidation time *)
Db.Session.set_validation_time ~__context ~self:session
- ~value:(Date.of_float now) ;
+ ~value:now ;
debug "updated validation time for session %s, sid %s "
(trackid session) authenticated_user_sid ;
(* let's also update the session's subject ref *)
@@ -634,12 +635,11 @@ let login_no_password_common ~__context ~uname ~originator ~host ~pool
(trackid session_id) pool
(match uname with None -> "" | Some u -> u)
originator is_local_superuser auth_user_sid (trackid parent) ;
+ let now = Date.now () in
Db.Session.create ~__context ~ref:session_id ~uuid ~this_user:user
- ~this_host:host ~pool
- ~last_active:(Date.of_float (Unix.time ()))
- ~other_config:[] ~subject ~is_local_superuser ~auth_user_sid
- ~validation_time:(Date.of_float (Unix.time ()))
- ~auth_user_name ~rbac_permissions ~parent ~originator ~client_certificate ;
+ ~this_host:host ~pool ~last_active:now ~other_config:[] ~subject
+ ~is_local_superuser ~auth_user_sid ~validation_time:now ~auth_user_name
+ ~rbac_permissions ~parent ~originator ~client_certificate ;
if not pool then
Atomic.incr total_sessions ;
Ref.string_of session_id
diff --git a/ocaml/xapi/xapi_session.mli b/ocaml/xapi/xapi_session.mli
index 853284f3c4c..c228fc3bfc5 100644
--- a/ocaml/xapi/xapi_session.mli
+++ b/ocaml/xapi/xapi_session.mli
@@ -87,7 +87,7 @@ val create_from_db_file :
(* for unit testing *)
val _record_login_failure :
__context:Context.t
- -> now:Xapi_stdext_date.Date.iso8601
+ -> now:Xapi_stdext_date.Date.t
-> uname:string option
-> originator:string option
-> record:[< `log_only | `log_and_alert]
diff --git a/ocaml/xapi/xapi_sr.ml b/ocaml/xapi/xapi_sr.ml
index fc7e5dd768a..d572660e72d 100644
--- a/ocaml/xapi/xapi_sr.ml
+++ b/ocaml/xapi/xapi_sr.ml
@@ -682,7 +682,7 @@ let update_vdis ~__context ~sr db_vdis vdi_infos =
~current_operations:[] ~allowed_operations:[]
~is_a_snapshot:vdi.is_a_snapshot
~snapshot_of:(find_vdi db_vdi_map vdi.snapshot_of)
- ~snapshot_time:(Date.of_string vdi.snapshot_time)
+ ~snapshot_time:(Date.of_iso8601 vdi.snapshot_time)
~sR:sr ~virtual_size:vdi.virtual_size
~physical_utilisation:vdi.physical_utilisation
~_type:(try Storage_utils.vdi_type_of_string vdi.ty with _ -> `user)
@@ -735,10 +735,10 @@ let update_vdis ~__context ~sr db_vdis vdi_infos =
debug "%s is_a_snapshot <- %b" (Ref.string_of r) vi.is_a_snapshot ;
Db.VDI.set_is_a_snapshot ~__context ~self:r ~value:vi.is_a_snapshot
) ;
- if v.API.vDI_snapshot_time <> Date.of_string vi.snapshot_time then (
+ if v.API.vDI_snapshot_time <> Date.of_iso8601 vi.snapshot_time then (
debug "%s snapshot_time <- %s" (Ref.string_of r) vi.snapshot_time ;
Db.VDI.set_snapshot_time ~__context ~self:r
- ~value:(Date.of_string vi.snapshot_time)
+ ~value:(Date.of_iso8601 vi.snapshot_time)
) ;
let snapshot_of = find_vdi db_vdi_map vi.snapshot_of in
if v.API.vDI_snapshot_of <> snapshot_of then (
diff --git a/ocaml/xapi/xapi_vbd.ml b/ocaml/xapi/xapi_vbd.ml
index 4284523e2ba..0bd805e5a26 100644
--- a/ocaml/xapi/xapi_vbd.ml
+++ b/ocaml/xapi/xapi_vbd.ml
@@ -260,7 +260,7 @@ let create ~__context ~vM ~vDI ~device ~userdevice ~bootable ~mode ~_type
let metrics = Ref.make ()
and metrics_uuid = Uuidx.to_string (Uuidx.make ()) in
Db.VBD_metrics.create ~__context ~ref:metrics ~uuid:metrics_uuid
- ~io_read_kbs:0. ~io_write_kbs:0. ~last_updated:(Date.of_float 0.)
+ ~io_read_kbs:0. ~io_write_kbs:0. ~last_updated:Date.epoch
~other_config:[] ;
(* Enable the SM driver to specify a VBD backend kind for the VDI *)
let other_config =
diff --git a/ocaml/xapi/xapi_vbd_helpers.ml b/ocaml/xapi/xapi_vbd_helpers.ml
index 3794d2c1fb7..c5a370df137 100644
--- a/ocaml/xapi/xapi_vbd_helpers.ml
+++ b/ocaml/xapi/xapi_vbd_helpers.ml
@@ -433,8 +433,7 @@ let copy ~__context ?vdi ~vm vbd =
let metrics_uuid = Uuidx.to_string (Uuidx.make ()) in
let vdi = Option.value ~default:all.API.vBD_VDI vdi in
Db.VBD_metrics.create ~__context ~ref:metrics ~uuid:metrics_uuid
- ~io_read_kbs:0. ~io_write_kbs:0. ~last_updated:(Date.of_float 0.)
- ~other_config:[] ;
+ ~io_read_kbs:0. ~io_write_kbs:0. ~last_updated:Date.epoch ~other_config:[] ;
Db.VBD.create ~__context ~ref:new_vbd ~uuid:vbd_uuid ~allowed_operations:[]
~current_operations:[] ~storage_lock:false ~vM:vm ~vDI:vdi
~empty:(all.API.vBD_empty || vdi = Ref.null)
diff --git a/ocaml/xapi/xapi_vdi.mli b/ocaml/xapi/xapi_vdi.mli
index 8e52daf8305..ff3e5a9e0ec 100644
--- a/ocaml/xapi/xapi_vdi.mli
+++ b/ocaml/xapi/xapi_vdi.mli
@@ -87,7 +87,7 @@ val pool_introduce :
-> physical_utilisation:int64
-> metadata_of_pool:[`pool] API.Ref.t
-> is_a_snapshot:bool
- -> snapshot_time:API.Date.iso8601
+ -> snapshot_time:API.Date.t
-> snapshot_of:[`VDI] API.Ref.t
-> cbt_enabled:bool
-> [`VDI] Ref.t
@@ -110,7 +110,7 @@ val db_introduce :
-> physical_utilisation:int64
-> metadata_of_pool:[`pool] API.Ref.t
-> is_a_snapshot:bool
- -> snapshot_time:API.Date.iso8601
+ -> snapshot_time:API.Date.t
-> snapshot_of:[`VDI] API.Ref.t
-> cbt_enabled:bool
-> [`VDI] Ref.t
@@ -208,7 +208,7 @@ val set_snapshot_of :
__context:Context.t -> self:[`VDI] API.Ref.t -> value:[`VDI] API.Ref.t -> unit
val set_snapshot_time :
- __context:Context.t -> self:[`VDI] API.Ref.t -> value:API.Date.iso8601 -> unit
+ __context:Context.t -> self:[`VDI] API.Ref.t -> value:API.Date.t -> unit
val set_metadata_of_pool :
__context:Context.t
diff --git a/ocaml/xapi/xapi_vif_helpers.ml b/ocaml/xapi/xapi_vif_helpers.ml
index b7fd5eadd2d..4a469b84368 100644
--- a/ocaml/xapi/xapi_vif_helpers.ml
+++ b/ocaml/xapi/xapi_vif_helpers.ml
@@ -298,8 +298,7 @@ let create ~__context ~device ~network ~vM ~mAC ~mTU ~other_config
and metrics_uuid = Uuidx.to_string (Uuidx.make ()) in
Db.VIF_metrics.create ~__context ~ref:metrics ~uuid:metrics_uuid
~io_read_kbs:0. ~io_write_kbs:0.
- ~last_updated:(Xapi_stdext_date.Date.of_float 0.)
- ~other_config:[] ;
+ ~last_updated:Xapi_stdext_date.Date.epoch ~other_config:[] ;
let (_ : unit) =
Db.VIF.create ~__context ~ref ~uuid:(Uuidx.to_string uuid)
~current_operations:[] ~allowed_operations:[] ~reserved:false ~device
diff --git a/ocaml/xapi/xapi_vm.ml b/ocaml/xapi/xapi_vm.ml
index 3e54a277592..3acd99a763e 100644
--- a/ocaml/xapi/xapi_vm.ml
+++ b/ocaml/xapi/xapi_vm.ml
@@ -617,8 +617,8 @@ let create ~__context ~name_label ~name_description ~power_state ~user_version
let current_domain_type = if suspended then domain_type else `unspecified in
Db.VM_metrics.create ~__context ~ref:metrics ~uuid:metrics_uuid
~memory_actual:0L ~vCPUs_number:0L ~vCPUs_utilisation ~vCPUs_CPU:[]
- ~vCPUs_params:[] ~vCPUs_flags:[] ~state:[] ~start_time:Date.never
- ~install_time:Date.never ~last_updated:Date.never ~other_config:[]
+ ~vCPUs_params:[] ~vCPUs_flags:[] ~state:[] ~start_time:Date.epoch
+ ~install_time:Date.epoch ~last_updated:Date.epoch ~other_config:[]
~hvm:false ~nested_virt:false ~nomigrate:false ~current_domain_type ;
let domain_type =
if domain_type = `unspecified then
@@ -652,7 +652,7 @@ let create ~__context ~name_label ~name_description ~power_state ~user_version
~power_state:_power_state ~allowed_operations:[] ~current_operations:[]
~blocked_operations:[] ~name_label ~name_description ~user_version
~is_a_template ~is_default_template:false ~transportable_snapshot_id:""
- ~is_a_snapshot:false ~snapshot_time:Date.never ~snapshot_of:Ref.null
+ ~is_a_snapshot:false ~snapshot_time:Date.epoch ~snapshot_of:Ref.null
~parent:Ref.null ~snapshot_info:[] ~snapshot_metadata:"" ~resident_on
~scheduled_to_be_resident_on ~affinity ~memory_overhead:0L
~memory_static_max ~memory_dynamic_max ~memory_target ~memory_dynamic_min
diff --git a/ocaml/xapi/xapi_vm_clone.ml b/ocaml/xapi/xapi_vm_clone.ml
index 46c1e310ac2..c2a5211d250 100644
--- a/ocaml/xapi/xapi_vm_clone.ml
+++ b/ocaml/xapi/xapi_vm_clone.ml
@@ -343,9 +343,9 @@ let copy_vm_record ?snapshot_info_record ~__context ~vm ~disk_op ~new_name
~snapshot_of:(if is_a_snapshot then vm else Ref.null)
~snapshot_time:
( if is_a_snapshot then
- Date.of_float (Unix.gettimeofday ())
+ Date.now ()
else
- Date.never
+ Date.epoch
)
~snapshot_info:
( match snapshot_info_record with
diff --git a/ocaml/xapi/xapi_vm_helpers.ml b/ocaml/xapi/xapi_vm_helpers.ml
index 1c295235b3c..0387dee1952 100644
--- a/ocaml/xapi/xapi_vm_helpers.ml
+++ b/ocaml/xapi/xapi_vm_helpers.ml
@@ -79,9 +79,7 @@ let set_is_a_template ~__context ~self ~value =
info "VM.set_is_a_template('%b')" value ;
let m = Db.VM.get_metrics ~__context ~self in
( if not value then
- try
- Db.VM_metrics.set_install_time ~__context ~self:m
- ~value:(Date.of_float (Unix.gettimeofday ()))
+ try Db.VM_metrics.set_install_time ~__context ~self:m ~value:(Date.now ())
with _ ->
warn
"Could not update VM install time because metrics object was missing"
@@ -1413,19 +1411,19 @@ let copy_metrics ~__context ~vm =
m
)
~start_time:
- (Option.fold ~none:Date.never
+ (Option.fold ~none:Date.epoch
~some:(fun x -> x.Db_actions.vM_metrics_start_time)
m
)
~install_time:
- (Option.fold ~none:Date.never
+ (Option.fold ~none:Date.epoch
~some:(fun x -> x.Db_actions.vM_metrics_install_time)
m
)
~state:
(Option.fold ~none:[] ~some:(fun x -> x.Db_actions.vM_metrics_state) m)
~last_updated:
- (Option.fold ~none:Date.never
+ (Option.fold ~none:Date.epoch
~some:(fun x -> x.Db_actions.vM_metrics_last_updated)
m
)
diff --git a/ocaml/xapi/xapi_vm_migrate.ml b/ocaml/xapi/xapi_vm_migrate.ml
index 8208cf89880..677da6fe8f1 100644
--- a/ocaml/xapi/xapi_vm_migrate.ml
+++ b/ocaml/xapi/xapi_vm_migrate.ml
@@ -1370,10 +1370,10 @@ let migrate_send' ~__context ~vm ~dest ~live:_ ~vdi_map ~vif_map ~vgpu_map
let r = Int64.compare v1.size v2.size in
if r = 0 then
let t1 =
- Date.to_float (Db.VDI.get_snapshot_time ~__context ~self:v1.vdi)
+ Date.to_unix_time (Db.VDI.get_snapshot_time ~__context ~self:v1.vdi)
in
let t2 =
- Date.to_float (Db.VDI.get_snapshot_time ~__context ~self:v2.vdi)
+ Date.to_unix_time (Db.VDI.get_snapshot_time ~__context ~self:v2.vdi)
in
compare t1 t2
else
diff --git a/ocaml/xapi/xapi_vmss.ml b/ocaml/xapi/xapi_vmss.ml
index 03badb83b60..d4a960cae81 100644
--- a/ocaml/xapi/xapi_vmss.ml
+++ b/ocaml/xapi/xapi_vmss.ml
@@ -228,7 +228,7 @@ let create ~__context ~name_label ~name_description ~enabled ~_type
let uuid = Uuidx.to_string (Uuidx.make ()) in
Db.VMSS.create ~__context ~ref ~uuid ~name_label ~name_description ~enabled
~_type ~retained_snapshots ~frequency ~schedule
- ~last_run_time:(Xapi_stdext_date.Date.of_float 0.) ;
+ ~last_run_time:Xapi_stdext_date.Date.epoch ;
ref
let destroy_all_messages ~__context ~self =
diff --git a/ocaml/xapi/xapi_xenops.ml b/ocaml/xapi/xapi_xenops.ml
index 48c51740c77..f50e692a555 100644
--- a/ocaml/xapi/xapi_xenops.ml
+++ b/ocaml/xapi/xapi_xenops.ml
@@ -2282,14 +2282,16 @@ let update_vm ~__context id =
Option.iter
(fun (_, state) ->
let metrics = Db.VM.get_metrics ~__context ~self in
- let start_time = Date.of_float state.Vm.last_start_time in
+ let start_time =
+ Date.of_unix_time state.Vm.last_start_time
+ in
if
start_time
<> Db.VM_metrics.get_start_time ~__context ~self:metrics
then (
debug
"xenopsd event: Updating VM %s last_start_time <- %s" id
- (Date.to_string (Date.of_float state.Vm.last_start_time)) ;
+ Date.(to_rfc3339 (of_unix_time state.Vm.last_start_time)) ;
Db.VM_metrics.set_start_time ~__context ~self:metrics
~value:start_time ;
if
@@ -2313,8 +2315,8 @@ let update_vm ~__context id =
"VM %s guest metrics update time (%s) < VM start time \
(%s): deleting"
id
- (Date.to_string update_time)
- (Date.to_string start_time) ;
+ (Date.to_rfc3339 update_time)
+ (Date.to_rfc3339 start_time) ;
Xapi_vm_helpers.delete_guest_metrics ~__context ~self ;
check_guest_agent ()
)
diff --git a/ocaml/xenopsd/lib/suspend_image.ml b/ocaml/xenopsd/lib/suspend_image.ml
index 029224e7b06..e08cb53c268 100644
--- a/ocaml/xenopsd/lib/suspend_image.ml
+++ b/ocaml/xenopsd/lib/suspend_image.ml
@@ -42,7 +42,7 @@ module Xenops_record = struct
[@@deriving sexp]
let make ?vm_str ?xs_subtree () =
- let time = Xapi_stdext_date.Date.(to_string (now ())) in
+ let time = Xapi_stdext_date.Date.(to_rfc3339 (now ())) in
let word_size = Sys.word_size in
{word_size; time; vm_str; xs_subtree}
diff --git a/ocaml/xenopsd/lib/xenops_server.ml b/ocaml/xenopsd/lib/xenops_server.ml
index 71ad563ed19..e65b929e1f4 100644
--- a/ocaml/xenopsd/lib/xenops_server.ml
+++ b/ocaml/xenopsd/lib/xenops_server.ml
@@ -1152,7 +1152,7 @@ module WorkerPool = struct
let t' = Xenops_task.to_interface_task t in
{
id= t'.Task.id
- ; ctime= t'.Task.ctime |> Date.of_float |> Date.to_string
+ ; ctime= t'.Task.ctime |> Date.of_unix_time |> Date.to_rfc3339
; dbg= t'.Task.dbg
; subtasks=
List.map
diff --git a/ocaml/xenopsd/xc/memory_breakdown.ml b/ocaml/xenopsd/xc/memory_breakdown.ml
index fae014a6ce3..54e739fe9aa 100644
--- a/ocaml/xenopsd/xc/memory_breakdown.ml
+++ b/ocaml/xenopsd/xc/memory_breakdown.ml
@@ -109,7 +109,7 @@ let xs_read_bytes_from_kib_key xs path =
(** {2 Host fields} *)
-let host_time _ = Date.to_string (Date.of_float (Unix.gettimeofday ()))
+let host_time _ = Date.(to_rfc3339 (now ()))
let host_total_bytes h =
Int64.to_string
diff --git a/ocaml/xenopsd/xc/memory_summary.ml b/ocaml/xenopsd/xc/memory_summary.ml
index c63e495ccb4..e2abb80264d 100644
--- a/ocaml/xenopsd/xc/memory_summary.ml
+++ b/ocaml/xenopsd/xc/memory_summary.ml
@@ -55,7 +55,7 @@ let _ =
in
if not !hash then (
Printf.printf "%s %Ld %Ld"
- (Date.to_string (Date.of_float (Unix.gettimeofday ())))
+ Date.(to_rfc3339 (now ()))
(total_pages ** one_page) (free_pages ** one_page) ;
let domains =
List.stable_sort (fun (a, _) (b, _) -> compare a b) domains
diff --git a/quality-gate.sh b/quality-gate.sh
index ab741ef3445..8e5a6ce8c26 100755
--- a/quality-gate.sh
+++ b/quality-gate.sh
@@ -40,7 +40,7 @@ mli-files () {
}
structural-equality () {
- N=10
+ N=11
EQ=$(git grep -r --count ' == ' -- '**/*.ml' ':!ocaml/sdk-gen/**/*.ml' | cut -d ':' -f 2 | paste -sd+ - | bc)
if [ "$EQ" -eq "$N" ]; then
echo "OK counted $EQ usages of ' == '"