poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] New functions and types for dealing with timestamps


From: John Darrington
Subject: [PATCH] New functions and types for dealing with timestamps
Date: Fri, 13 Dec 2019 09:19:17 +0100

        * doc/poke.texi (Dates and Times): New chapter.
        * src/std.pk (POSIX_Time32, POSIX_Time64): New types.
          (ptime): New function.
        * testsuite/poke.std/time32.pk: New file.
---
 ChangeLog                    |   6 +++
 doc/poke.texi                |  55 +++++++++++++++++++++++
 src/std.pk                   | 103 +++++++++++++++++++++++++++++++++++++++++++
 testsuite/poke.std/time32.pk |  13 ++++++
 4 files changed, 177 insertions(+)
 create mode 100644 testsuite/poke.std/time32.pk

diff --git a/ChangeLog b/ChangeLog
index b76436f..1034abf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2019-12-15 John Darrington <address@hidden>
 
+       * doc/poke.texi (Date and Time Functions): New chapter.
+       * src/std.pk (posix_time32): New type.
+       * testsuite/poke.std/time32.pk: New file.
+
+2019-12-15 John Darrington <address@hidden>
+
        * doc/poke.texi (Scripts): Elaborate on what scripts are
        (and what they are not).
 
diff --git a/doc/poke.texi b/doc/poke.texi
index 06bf29b..0050e11 100644
--- a/doc/poke.texi
+++ b/doc/poke.texi
@@ -109,6 +109,7 @@ The Standard Library
 * String Functions::           Functions which deal with strings.
 * Sorting Functions::          qsort.
 * CRC Functions::               Cyclic Redundancy Checksums.
+* Dates and Times::             Processing and displaying dates and times.
 
 Hacking poke
 * Writing Commands::           Extending poke with new commands.
@@ -4103,6 +4104,60 @@ defun crc32 = (byte[] @var{buf}) uint<32>: @{ @dots{} @}
 This function returns the 32 bit CRC for the data contained in the
 array @var{buf}.
 
+@node Dates and Times
+@chapter Dates and Times
+@cindex date
+@cindex time
+@cindex @code{POSIX_Time32}
+
+Often a format encodes a date and time expressed as the number of seconds
+since midnight, January@tie{}1st 1970@.   You could map these
+simply as integers.  However, the standard library provides two
+types @code{POSIX_Time32} and @code{POSIX_Time64} which include
+pretty-printers (@pxref{Pretty Printers}) to
+display the date in a human readable format.
+The definition is:
+
+@example
+deftype POSIX_Time@var{size} = struct
+@{
+  uint<@var{size}>  seconds;
+
+  defun _print = void:
+  @{ @dots{} @}
+@}
+@end example
+
+@noindent
+where @var{size} is either 32 or 64@.
+When pretty printing is enabled, a mapped value of these types will
+display similar to
+
+@example
+#<2019-Dec-12 8:54:56>
+@end example
+
+@noindent
+whereas when pretty printing is not enabled, this example would be displayed 
as:
+
+@example
+POSIX_Time32 @{seconds=1576140896U@}
+@end example
+
+@noindent
+Note that timestamps of this type do not account for leap seconds and
+are agnostic towards timezone.
+
+@cindex @code{ptime}
+Occasionally you might wish to print an unmapped timestamp value in a
+human readable format.  To do this, you can use the @code{ptime} function,
+which is defined as follows:
+
+@example
+defun ptime = (uint<64> seconds) void:
+@{ @dots{} @}
+@end example
+
 @node Writing Commands
 @chapter Writing Commands
 
diff --git a/src/std.pk b/src/std.pk
index 0da1b93..8c3037e 100644
--- a/src/std.pk
+++ b/src/std.pk
@@ -222,6 +222,109 @@ defun crc32 = (byte[] buf) uint<32>:
    return update (0xffffffffU, buf) ^ 0xffffffffU;
   }
 
+/*** Date and Time functions.  */
+
+defun ptime = (uint<64> seconds) void:
+{
+    defun days_in_year = (int year) int:
+    {
+      if (year % 400 == 0) return 366;
+      if (year % 100 == 0) return 365;
+      if (year % 4 == 0) return 366;
+      return 365;
+    }
+
+    defun days_in_month = (int year, int month) int:
+    {
+      if (month < 0)
+       raise E_out_of_bounds;
+      if (month > 11)
+       raise E_out_of_bounds;
+
+      /* Deal with February.  */
+      if (month == 1)
+       {
+         if (days_in_year (year) == 366)
+           return 29;
+         else
+           return 28;
+       }
+
+      /* 30 days hath Sept, Apr, June & Nov ...  */
+      for (m in [8, 3, 5, 10])
+       {
+         if (month == m)
+           return 30;
+       }
+
+      return 31;
+    }
+
+    defvar month_names = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
+
+    defvar year = 1970;
+    defvar month = 0;
+    defvar day = 0;
+    defvar hour = 0;
+    defvar minute = 0;
+    while (seconds >= 0)
+      {
+       if (seconds < 24 * 60 * 60)
+         {
+           hour = seconds / 3600;
+           seconds = seconds % 3600;
+           minute = seconds / 60;
+           seconds = seconds % 60;
+           break;
+         }
+       else if (seconds < days_in_month (year, month) * 24 * 60 * 60)
+         {
+           seconds = seconds - 24 * 60 * 60;
+           day = day + 1;
+         }
+       else if (seconds < days_in_year (year) * 24 * 60 * 60)
+         {
+           seconds = seconds - days_in_month (year, month) * 24 * 60 * 60;
+           month = month + 1;
+         }
+       else
+         {
+           seconds = seconds - days_in_year (year) * 24 * 60 * 60;
+           year = year + 1;
+         }
+      }
+
+    printf ("%<date-time:%i32d-%s-%i32d %i32d:%i32d:%i32d%>",
+           year, month_names[month], day + 1,
+           hour, minute, seconds);
+}
+
+deftype POSIX_Time32 = struct
+{
+  uint<32>  seconds;
+
+  defun _print = void:
+  {
+    print "#<";
+    ptime (seconds);
+    print ">";
+  }
+};
+
+deftype POSIX_Time64 = struct
+{
+  uint<64>  seconds;
+
+  defun _print = void:
+  {
+    print "#<";
+    ptime (seconds);
+    print ">";
+  }
+};
+
+
 
 /*** Miscellanea.  */
 
diff --git a/testsuite/poke.std/time32.pk b/testsuite/poke.std/time32.pk
new file mode 100644
index 0000000..7b5be90
--- /dev/null
+++ b/testsuite/poke.std/time32.pk
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+
+/* { dg-command {.set pretty-print yes} } */
+/* { dg-command {.set endian host} } */
+
+
+/* { dg-data {i*} {0 1576140896} } */
+
+/* { dg-command {POSIX_Time32 @ 0#B} } */
+/* { dg-output "#<1970-Jan-1 0:0:0>\n" } */
+
+/* { dg-command {POSIX_Time32 @ 4#B} } */
+/* { dg-output "#<2019-Dec-12 8:54:56>\n" } */
-- 
2.11.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]