C-Kermit 7.0 Case Study #17

[ Previous ] [ Next ] [ Index ] [ C-Kermit Home ] [ Kermit Home ]

Article: 11087 of comp.protocols.kermit.misc
From: fdc@watsun.cc.columbia.edu (Frank da Cruz)
Newsgroups: comp.protocols.kermit.misc
Subject: Case Study #17: Fun with Dates and Times
Date:27 Jan 2000 23:52:05 GMT
Organization: Columbia University

C-Kermit 7.0 (and Kermit 95 1.1.18 when it comes out) let you use dates and times as "native" data types in your commands and scripts. We spoke about this a little bit in the "How Do I Delete Files More Than a Week Old?" example but that just skimmed the surface.

I won't bother listing the rules for writing dates and times; they are spelled out in Section 1.6 of the C-Kermit 7.0 Update Notes. Assuming you know how to write dates and times, what can you do with them?

You have already seen how they can be used as file selectors. For example, to send all files that were created in December 1999, you could:

  SEND /NOT-BEFORE:1999-12-01 /BEFORE:2000-01-01 *.*

/NOT-BEFORE is almost the same as /AFTER, except /NOT-BEFORE includes the given date-time (in this case the implied time of 00:00:00 on December 1), whereas /AFTER excludes it. A fine point indeed! (Of course there is also a /NOT-AFTER switch, which has the same relationship to /BEFORE.)

To illustrate dates with explicit times, here is a command to send log files created after noon on the 27th day of January of this year:

  SEND /AFTER:{2000-01-27 12:00:00} *.log

A date-time is a single field (or "word") in Kermit syntax, so must be enclosed in braces if it contains any spaces, as shown above (of course other variations are possible).

To experiment with date-time formats, use C-Kermit's new DATE command. If you type "date" by itself, it prints the current date and time. If you follow it by something, C-Kermit tries to interpret the "something" as a date and/or time and prints the result (or an error message).

Perhaps the most interesting aspect of C-Kermit's new date-time support is the ability to do date and time arithmetic. This works in two ways. First, by using the built-in relative date syntax: YESTERDAY, TOMORROW, +3DAYS, -6WEEKS, +12YEARS, etc, for example:

  DELETE /BEFORE:-2WEEKS *.*

All the built-in symbolic dates are relative to "today", the current date.

You can also perform explicit calculations, such as obtaining a date that is a given number of days after a given date, or finding out the day of the week for a given date.

All of C-Kermit's date calculations are based on the Modified Julian Date (MJD), which is the number of days since 17 November 1858. For dates prior to 17 Nov 1858, the MJD is negative. MJDs are scalar counting numbers (unlike the "yyyyddd" format, often but improperly called the Julian date), so you can do arithmetic on them. For example, if today's MJD is 51570, then 100 days from today, the MJD will be 51570 + 100 = 51670.

MJDs have some other interesting properties too:

C-Kermit 7.0 includes functions to convert date-time strings to MJD and vice versa. For example, here's how to get the date 100 days from today:

  .\%m := \fmjd(\v(date))     ; Convert today's date to MJD
  echo \fmjd2date(\%m+100)    ; Add 100 and convert back to a date.

The result is "20000506", or 6 May 2000, which is:

  echo \fday(20000506)
  Sat

... a Saturday. Did you ever wonder what day of the week you were born? Ask Kermit (substituting your actual birthday):

  echo \fday(27 jan 1958)
  Mon

The \fday() function returns the English 3-letter day of the week abbreviation; \fnday() returns a day-of-week number, 0-6; the argument is a date-time string. You can use \fmodulus(MJD,7) if you have an MJD.

By the way, the "variablename = value" notation is new to C-Kermit 7.0. The assignment operator can be "=", which does what DEFINE does; ":=" does what ASSIGN does, and "::=" evaluates the value as an arithmetic expression and then ASSIGNs it to the variable (see Section 7.9.1 of the of the C-Kermit 7.0 Update Notes for details).

C-Kermit's new date conversion and arithmetic functions let us answer questions like "What is the first Friday after a given date?". Questions like this come up all the time in data processing. Let's say the variable \%d contains the "given date":

  .\%m ::= \fmjd(\%d)+1       ; Convert day after given date to MJD.
  .\%x := \fmod(\%m,7)        ; Day of week of day after given date.
  .\%y := \fmod(9-\%x,7)      ; Days until Friday (0-6)
  .\%e := \fmjd2date(\%m+\%y) ; Date of first Friday after given date.

C-Kermit doesn't have a built-in function that returns the date of the first Friday after a given date, but (as explained in Using C-Kermit, 2nd Ed, page 399), you can define your own:

  define FRIDAYAFTER {
      local \%m \%x \%y
      .\%m ::= \fmjd(\%*)+1   ; "\%*" allows for spaces in argument
      .\%x := \fmod(\%m,7)    ; (C-Kermit 7.0 Update Notes  Section 7.5)
      .\%y := \fmod(9-\%x,7)
      return \fmjd2date(\%m+\%y)
  }

You can invoke it like this:

  \fexec(fridayafter,27 jan 2000)

And you can use it for file selection like this:

  delete /before:\fexec(fridayafter,27 jan 1999)

C-Kermit also has another set of functions for dealing with the more common (but less useful) yyyyddd (year, day of year) format: \fdoy(date-time), \fdoy2date(doy). You can read about them in Section 1.6 of the C-Kermit 7.0 Update Notes.

Arithmetic can also be done with times-of-day. Functions are available to give the current time in hh:mm:ss notation and as seconds since midnight. New functions \fntime(hh:mm:ss) converts the given time to seconds since midnight, and \fn2time(n) converts the given number of seconds since midnight to hh:mm:ss format. So given a particular time, you can convert it to seconds-since-midnight, do any desired arithmetic on it, and then convert the result back to hh:mm:ss format.

To illustrate, let's see what the date and time will be a million seconds from now:

  .\%t := \v(ntime)                  ; Current time secs since midnight
  .\%d := \fmjd(\v(date))            ; MJD of today
  incr \%t 1000000                   ; Add a million seconds to current time
  incr \%d (\%t/86400)               ; Extract days and add to MJD
  .\%t := \fmod(\%t,86400)           ; Remainder is time of day
  echo \fmjd2date(\%d) \fn2time(\%t) ; Print the result

(86400 is the number of seconds in a day.)

C-Kermit's date/time functions don't use any platform-specific APIs (except obviously to obtain the current date and time), so they should work uniformly everywhere. The range of date arithmetic depends on the integer size of your computer and the code generated by the C compiler.

And in case you were wondering, the true Julian date is the number of days since Noon, 1 January 4713 BC (BCE). But this has become a rather large number (too large for 16- or even 18-bit computer words), so the MJD is used instead in most computer applications and is, in fact, the internal date representation in some well-known computer operating systems (but not Unix).

- Frank

[ Top ] [ Previous ] [ Next ] [ Index ] [ C-Kermit Home ] [ Kermit Home ]


C-Kermit 7.0 / Columbia University / kermit@columbia.edu / 27 Jan 2000