Epoch in F#

A common requirement in programs is getting the number of seconds, milliseconds, or nanoseconds since the Unix epoch. Here’s how to do it in F#.

open System

let main() =
    // Use DateTime.UtcNow to get the current UTC time
    let now = DateTime.UtcNow
    printfn "%A" now

    // Convert to Unix timestamp (seconds since epoch)
    let unixTimestamp = (now.ToUniversalTime() - DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds
    printfn "%f" unixTimestamp

    // Get milliseconds since epoch
    let unixTimestampMillis = (now.ToUniversalTime() - DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds
    printfn "%f" unixTimestampMillis

    // Get nanoseconds since epoch (note: F# doesn't have nanosecond precision, so this is an approximation)
    let unixTimestampNanos = (now.ToUniversalTime() - DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds * 1000000.0
    printfn "%f" unixTimestampNanos

    // Convert Unix timestamp back to DateTime
    let dateFromUnixTimestamp = DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(unixTimestamp)
    printfn "%A" dateFromUnixTimestamp

    // Convert Unix timestamp (in nanoseconds) back to DateTime
    let dateFromUnixTimestampNanos = DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(unixTimestampNanos / 1000000.0)
    printfn "%A" dateFromUnixTimestampNanos

main()

To run the program, save it as Epoch.fs and use the F# compiler:

$ fsharpc Epoch.fs
$ mono Epoch.exe
5/7/2023 3:45:30 PM
1683474330.000000
1683474330000.000000
1683474330000000000.000000
5/7/2023 3:45:30 PM
5/7/2023 3:45:30 PM

In F#, we use the System.DateTime struct to work with dates and times. The DateTime.UtcNow property gives us the current UTC time. To get the Unix timestamp, we subtract the Unix epoch (January 1, 1970) from the current time and convert the result to seconds, milliseconds, or an approximation of nanoseconds.

F# doesn’t have built-in methods for Unix time like Unix(), UnixMilli(), or UnixNano(), so we perform the calculations manually. Also, F# (and .NET in general) doesn’t provide nanosecond precision, so the nanosecond calculation is an approximation.

To convert back from a Unix timestamp to a DateTime, we add the number of seconds (or milliseconds for the nanosecond case) to the Unix epoch.

Next, we’ll look at another time-related task: time parsing and formatting in F#.