The standard way to represent time is as an offset from the epoch in milliseconds. This is the de-facto representation in the JVM, JS VM, transit, and many storage systems. As such, it is the standard for the instant type in RAD. User interfaces also need to localize the date and time to either the user or context of the form/report in question.

There are standard implementations of localization for js and the JVM, but since we’re using CLJC already it makes the most since to us to just use cljc.java-time , which is a library that unifies the API of the standard JVM Time API. This makes it much simple to write localized support for dates and times in CLJC files. To date we are avoiding the tick library because it is not yet as mature, and is overkill for RAD itself (though you can certainly use it in your applications).

At the time of this writing RAD supports only the storage of instants (Java/js Date objects), and requires that you select a time-zone for the context of your processing. The concept of LocalDate and LocalTime can easily be added, but for now the style of the UI control determines what the user interaction looks like. This means that when you ask the user for a date, it will be stored as a specific time on a specific date in a specific time zone.

For example, an Invoice might require a date (which could be in the context of the receiver or the shipper). The "ideal" solution is to do time zone offset calculations, but a reasonable approximation might be to just store the date relative to noon (or midnight, etc.) in the time zone of the user. This can be supported with a simple UI control style:

Of course you can provide your own style definitions for controls, and you can also choose to store things like "Local Dates" as simple strings (or a LocalDate type if your storage engine has one) in your database if you wish to completely avoid the time zone complication. At that point you could also add Transit support for local dates to your network layer, and keep those items in the correct type in a full-stack manner.

Note At the time of this writing the date-time namespace requires the 10-year time zone range from Joda Timezone. This will most likely be removed from RAD and changed to a requirement for your application, since you can then select the time zone file that best meets your application’s size and functionality requirements.

In order to use date/time support in RAD you must set the time zone so that RAD knows how to adjust local date and times into proper UTC offsets. Setting the time zone can be done in a couple of ways, depending on the desired usage context.

It is important to note that the server (CLJ) side will typically only deal with already-adjusted UTC offsets. Thus, the code on the server mostly just read/saves the values without having to do anything else. A UTC offset is unambiguous, just not human friendly. The user interface is where RAD does this human interfacing.

In CLJS you are commonly dealing with a lot of (potentially behind-the-scenes) asynchronous logic. Fulcro makes most of the model appear synchronous, but the reality is quite different in implementation. Fortunately, most UI contexts are aimed at the user, and that user usually has a particular time zone that is of interest to them. Thus, the time zone on the client side can usually be set to some reasonable default on client startup (perhaps based on the browser’s known locale) and further refined when a user logs in (via a preference that you allow them to set).

Thus, CLJS code will typically call (datetime/set-timezone! "America/Los_Angeles") , where the string argument is one of the standard time zone names. The are available from (cljc.java-time.zone-id/get-available-zone-ids) .

( defn init [] (log/info " Starting App " ) (datetime/set-timezone! " America/Los_Angeles " ) (form/install-ui-controls! app sui/all-controls) (attr/register-attributes! model/all-attributes) (app/mount! app Root " app " ))

Note The above action is all that is needed to get most of RAD working. The remainder of the date/time support is used internally, and can also be convenient for your own logic as your requirements grow.

It is also possible that you may wish to temporarily override the currently-selected time zone for some context. This is true for CLJS (though you will have to be careful to manage async behavior there), and is central to CLJ operation.

In CLJ your normal reads and mutations will be dealing with UTC offsets that have already been properly adjusted in the client. There are times when you’ll want to deal with timezone-centric data (in reports and calculations, for example, you might need to choose a range from the user’s perspective).

Most of the functions in the date-time namespace allow you to pass the zone name (string version of zone id) as an optional parameter, but the default value comes from the dynamic var datetime/current-timezone as a ZoneID instance, not a string.

So, you can get a thread-local binding for this with the standard Clojure:

( binding [datetime/*current-timezone* (zone-id/of " America/New_York " )] .. . )

The macro with-timezone makes this a less noisy:

(with-timezone " America/New_York " .. . )