poke-devel
[Top][All Lists]
Advanced

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

[PATCH] New function posix_time32 to map timestamps


From: John Darrington
Subject: [PATCH] New function posix_time32 to map timestamps
Date: Thu, 12 Dec 2019 11:58:21 +0100

        * doc/poke.texi (Date and Time Functions): New chapter.
        * src/std.pk (posix_time32): New type.
        * testsuite/poke.std/time32.pk: New file.
---
 ChangeLog                    |  6 ++++
 doc/poke.texi                | 42 ++++++++++++++++++++++
 src/std.pk                   | 83 ++++++++++++++++++++++++++++++++++++++++++++
 testsuite/poke.std/time32.pk | 13 +++++++
 4 files changed, 144 insertions(+)
 create mode 100644 testsuite/poke.std/time32.pk

diff --git a/ChangeLog b/ChangeLog
index 0871856..92b1d31 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..e121597 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.
+* Date and Time Functions::     Functions for processing dates and times.
 
 Hacking poke
 * Writing Commands::           Extending poke with new commands.
@@ -4103,6 +4104,47 @@ 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 Date and Time Functions
+@chapter Date and Time Functions
+@cindex date
+@cindex time
+@cindex @code{posix_time32}
+
+Often a format encodes a timestamp expressed as the number of seconds
+since midnight, January@tie{}1st 1970@.   You can map this
+simply as a @code{uint<32>}.  However, the standard library provides
+a type which includes a pretty-printer (@pxref{Pretty Printers}) to
+display the date in a human readable format:
+
+@example
+deftype posix_time32 = struct
+@{
+  uint<32>  seconds;
+
+  defun _print = void:
+  @{ @dots{} @}
+@}
+@end example
+
+@noindent
+When pretty printing is enabled, a mapped value of type @code{posix_time32} 
will
+display similar to
+
+@example
+#<2019-Dec-12 8:54:56>
+@end example
+
+@noindent
+wheras 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.
+
 @node Writing Commands
 @chapter Writing Commands
 
diff --git a/src/std.pk b/src/std.pk
index 0da1b93..d421d94 100644
--- a/src/std.pk
+++ b/src/std.pk
@@ -222,6 +222,89 @@ defun crc32 = (byte[] buf) uint<32>:
    return update (0xffffffffU, buf) ^ 0xffffffffU;
   }
 
+/*** Date and Time.  */
+
+deftype posix_time32 = struct
+{
+  uint<32>  seconds;
+
+  defun _print = 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;
+         }
+      }
+    print "#<";
+    printf ("%<date-time:%i32d-%s-%i32d %i32d:%i32d:%i32d%>",
+           year, month_names[month], day + 1,
+           hour, minute, seconds);
+    print ">";
+  }
+};
 
 /*** Miscellanea.  */
 
diff --git a/testsuite/poke.std/time32.pk b/testsuite/poke.std/time32.pk
new file mode 100644
index 0000000..22d1046
--- /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]