9front - general discussion about 9front
 help / color / mirror / Atom feed
From: ori@eigenstate.org
To: 9front@9front.org
Subject: Date and time handling.
Date: Tue, 7 Apr 2020 20:56:06 -0700	[thread overview]
Message-ID: <09D185393BD8E86D37288FC967E7EA69@eigenstate.org> (raw)

Hi,

Date handling on 9front is almost adequate today if you don't
have to parse dates or deal with timezones, and don't do
multithreading. Otherwise, it's difficult to get right, and
we often don't.

We've got a crappy home-rolled date parser in seconds(1),
a few in the upas source tree to deal with mail formats,
and git9 has a few hacks around this as well.

Out of tree, joe9 has been trying to write code that takes
stock information in one timezone and moves them to another,
and our APIs there are completely inadequate.

So, I tried to write a library that is adequate, without
being complicated.

It allows working with times in multiple timezones at the
same time. It is thread safe, including timezone loading.
It allows parsing and formatting arbitrary formats. It lets
you adjust the day and figure out the timeshift-shift
adjusted time.

Eventually, when it's ready (not yet), I'd like to put this
into libc. The API additions are small, and all of our curent
time APIs can be implemented trivially in terms of this api.
At worst, I'd like to add the field additions from struct tmd
to it.

There are a few known bugs -- not all fields of the time struct
are filled in yet, for example.

The code is here:

	https://git.eigenstate.org/ori/date.git

The formatted draft of the manpage is below, for comments and
thoughts:

     TMDATE(2)                                               TMDATE(2)

     NAME
          tmnow, tmtime, tmstime, tmshiftzone, tmparse, tmfmt, tmnorm,
          - convert date and time

     SYNOPSIS
          #include <u.h>
          #include <libc.h>

          typedef struct Tmd Tmd;
          struct {
                vlong    abs; /* milliseconds since Jan 1 1970, GMT */
                int sec; /* seconds (range 0..59) */
                int min; /* minutes (0..59) */
                int hour;     /* hours (0..23) */
                int mday;     /* day of the month (1..31) */
                int mon; /* month of the year (0..11) */
                int year;     /* year A.D. - 1900 */
                int wday;     /* day of week (0..6, Sunday = 0) */
                int yday;     /* day of year (0..365) */
                char     zone[];   /* time zone name */
                int tzoff;    /* time   zone delta from GMT */
          };

          Tm   *tmnow(Tm *tm, char *tz);
          Tm   *tmtime(Tm *tm, vlong abs, char *tz);
          Tm   *tmstime(Tm *tm, vlong sec, char *tz);
          Tm   *tmshiftzone(Tm *dst, Tm *src, char *tz);
          Tm   *tmparse(Tm *dst, char *fmt, char *tm);
          int   tmfmt(char *buf, usize nbuf, char *fmt, Tm *tm);
          void tmnorm(Tm *tm);
          void tmfmtinstall(char *fmt);

     DESCRIPTION
          This family of functions handles simple date and time manpu-
          lation.  Times are represented as an absolute instant in
          time, combined with a time zone.

          Time zones are represented as strings.  They can be provided
          as the abbreviated timezone name, the full timezone name,
          the path to a timezone file, or an absolute offset in the
          HHMM form.

          When given as a timezone name, any instant-dependent adjust-
          ments such as leap seconds and daylight savings time will be
          applied to the derived fields of struct tm, but will not
          affect the absolute time.  The time zone name local always
          refers to the time in /env/timezone.

          Tmnow gets the current time of day in the requested time
          zone.

          Tmtime converts the millisecond-resolution timestamp 'abs'
          into a Tm struct in the requested timezone.

          Tmstime is identical to tmtime, but accepts the time in sec-
          onds.

          Tmshiftzone moves a time from one timezone to another, doing
          the appropriate conversions.

          Tmparse parses a time from a string according to the format
          argument. The format argument takes the form of a special
          date string, with the following components:

          1,Jan,January
               Represents the month in numeric, short, or long form,
               respectively.

          2    The day of month.

          3,Mon,Monday
               The day of week in numeric, short, or long form,
               respectively.

          3,15 The hour in 12 or 24 hour time, respectively.

          4    The minute.

          5    The second.

          6,2006
               The year in 2 and 4 digit forms, respectively.

          7,MST
               The time zone offset in numeric or abbreviated form.
               As a special case, 7:00 will fill in both the hour and
               minutes in the timezone.

          _    Pads the following field with spaces.  0 Pads the fol-
               lowing field with zeroes.

          If the format argument is nil, it makes an attempt to parse
          common human readable date formats.  These formats include
          ISO-8601,RFC-3339 and RFC-2822 dates.

          Tmfmt formats a Tm struct according to the format fmt. If
          fmt is nil, we format as in ctime(2). At most nbuf-1 char-
          actters are written into buf, which is nul-terminated.

          Tmrecalc takes a manually adjusted Tm structure, and recal-
          culates the absolute time from it.  This recalculation
          respects the time zone stored in struct tm.  It also takes
          out of range values and wraps them around, simplifying cal-
          culations

          Tmfmtinstall installs a time format specifier %T. The time
          format behaves as in tmfmt

     Examples
          All examples assume tmfmtinstall has been called.

          Get the current date in the local timezone, GMT, and
          US_Pacific time. Print it using the default format.

           Tm t;
           print("local: %T0, tmnow(&t, "local"));
           print"gmt: %T0, tmnow(&t, "GMT"));
           print("eastern: %T0, tmnow(&t, "US_Pacific"));

          Compare if two times are the same, regardless of timezone.

           Tm a, b;

           tmparse(&a, nil, "Tue Dec 10 12:36:00 PST 2019");
           tmparse(&b, nil, "Tue Dec 10 15:36:00 EST 2019");
           if(a.abs == b.abs)
                print("same0);
           else
                print("different0);

          Add a day to two times. Because we picked daylight savings
          time to adjust over, only 23 hours are added.

           Tm t;
           tmparse(&t, nil, "Sun Nov 2 13:11:11 PST 2019");
           tm.day++;
           tmrecalc(&t);
           print("%T", &t); /*  Mon Nov 3 13:11:11 PST 2019 */



             reply	other threads:[~2020-04-08  3:56 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-08  3:56 ori [this message]
2020-04-08  6:48 ` [9front] " Steve Simon
2020-04-09 14:12   ` ori
2020-04-12  6:20   ` ori
2020-04-12 18:27 ` magma698hfsp273p9f
2020-04-13  0:36   ` [9front] " ori
2020-04-16 20:40     ` ori
2020-05-04  4:08       ` ori
2020-05-05 17:29         ` magma698hfsp273p9f

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=09D185393BD8E86D37288FC967E7EA69@eigenstate.org \
    --to=ori@eigenstate.org \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).