From f1d2a1a12f0343759ad4714213959fc9dba5a428 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sun, 22 May 2022 21:40:06 -0400 Subject: [PATCH] Added better Duration toString and Date makeWithYear functionality --- .../src/components/SquiggleChart.tsx | 5 +-- .../ReducerInterface_DateTime.res | 9 +++-- .../squiggle-lang/src/rescript/Utility/E.res | 36 +++++++++++++++---- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 5214dafc..fe79a018 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -192,15 +192,16 @@ const SquiggleItem: React.FC = ({ case "date": return ( - {expression.value.toString()} + {expression.value.toDateString()} ); - case "timeDuration": + case "timeDuration":{ return ( ); + } case "lambda": return ( EvString(E.Date.toString(t))->Ok->Some | ("makeDateFromYear", [EvNumber(year)]) => - EvDate(E.Date.makeWithYM(~year, ~month=0.0, ()))->Ok->Some + switch E.Date.makeWithYear(Belt.Float.toInt(year)) { + | Ok(t) => EvDate(t)->Ok->Some + | Error(e) => RETodo(e)->Error->Some + } | ("fromMilliseconds", [EvNumber(f)]) => EvDate(E.Date.fromFloat(f))->Ok->Some | ("toMilliseconds", [EvDate(f)]) => EvNumber(E.Date.toFloat(f))->Ok->Some | ("subtract", [EvDate(d1), EvDate(d2)]) => @@ -22,14 +25,16 @@ let dateDispatch = (call: ExpressionValue.functionCall, env: DistributionOperati } } -let durationDispatch = (call: ExpressionValue.functionCall, env: DistributionOperation.env): option< +let durationDispatch = (call: ExpressionValue.functionCall, _: DistributionOperation.env): option< result, > => { switch call { | ("toString", [EvTimeDuration(t)]) => EvString(E.Duration.toString(t))->Ok->Some | ("hours", [EvNumber(f)]) => EvTimeDuration(E.Duration.fromHours(f))->Ok->Some + | ("days", [EvNumber(f)]) => EvTimeDuration(E.Duration.fromDays(f))->Ok->Some | ("years", [EvNumber(f)]) => EvTimeDuration(E.Duration.fromYears(f))->Ok->Some | ("toHours", [EvTimeDuration(f)]) => EvNumber(E.Duration.toHours(f))->Ok->Some + | ("toDays", [EvTimeDuration(f)]) => EvNumber(E.Duration.toDays(f))->Ok->Some | ("toYears", [EvTimeDuration(f)]) => EvNumber(E.Duration.toYears(f))->Ok->Some | ( ("add" | "subtract" | "multiply" | "divide") as op, diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index d2ad62f4..088867c9 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -840,7 +840,7 @@ module Duration = { let minute = Belt.Float.fromInt(60 * 1000) let hour = Belt.Float.fromInt(60 * 60 * 1000) let day = Belt.Float.fromInt(24 * 60 * 60 * 1000) - let year = Belt.Float.fromInt(24 * 60 * 60 * 1000 * 365) + let year = Belt.Float.fromInt(24 * 60 * 60 * 1000) *. 365.25 let fromFloat = (f: float): t => f let toFloat = (d: t): float => d let fromHours = (h: float): t => h *. hour @@ -849,7 +849,19 @@ module Duration = { let toHours = (t: t): float => t /. hour let toDays = (t: t): float => t /. day let toYears = (t: t): float => t /. year - let toString = (t: t) => `${Float.with2DigitsPrecision(t)}ms` + let toString = (t: t): string => { + if t >= year { + Float.with3DigitsPrecision(t /. year) ++ " years" + } else if t >= day { + Float.with3DigitsPrecision(t /. day) ++ " days" + } else if t >= hour { + Float.with3DigitsPrecision(t /. hour) ++ " hours" + } else if t >= minute { + Float.with3DigitsPrecision(t /. minute) ++ " minutes" + } else { + Float.toFixed(t) ++ "ms" + } + } let add = (t1, t2): t => t1 +. t2 let subtract = (t1, t2): t => t1 -. t2 let multiply = (t1, t2): t => t1 *. t2 @@ -857,12 +869,24 @@ module Duration = { } module Date = { + //The Rescript/JS implementation of Date is pretty mediocre. It would be good to improve upon later. type t = Js.Date.t - type year - let makeWithYM = Js.Date.makeWithYM - let toString = Js.Date.toString - let fromFloat = Js.Date.fromFloat let toFloat = Js.Date.getTime + let getFullYear = Js.Date.getFullYear + + //The Js.Date.makeWithYM function accepts a float, but only treats it as a whole number. + //Our version takes an integer to make this distinction clearer. + let makeWithYear = (y: int): result => { + if y < 100 { + Error("Year must be over 100") + } else if y > 200000 { + Error("Year must be less than 200000") + } else { + Ok(Js.Date.makeWithYM(~year=Belt.Float.fromInt(y), ~month=0.0, ())) + } + } + let toString = Js.Date.toDateString + let fromFloat = Js.Date.fromFloat let fmap = (t: t, fn: float => float) => t->toFloat->fn->fromFloat let subtract = (t1: t, t2: t) => { let (f1, f2) = (toFloat(t1), toFloat(t2))