Source file timezone.icn
#
# $Id: timezone.icn,v 1.3 2006-07-10 14:33:39 rparlett Exp $
#
# This file is in the public domain.
#
# Author: Robert Parlett (parlett@dial.pipex.com)
#

package util

global known_timezones, system_timezone, utc_timezone

class Timezone(offset, id)
   method get_id()
      return id
   end

   method get_offset()
      return offset
   end

   initially(a[])
      static once
      if /once then {
	 init_timezone()
	 once := 1
	 }
      if *a = 0 then {
	 id := "UTC"
	 offset := 0
	 }
      else if *a = 1 then {
	 if ::type(a[1]) == "integer" then {
	    offset := a[1]
	    id := (if offset < 0 then "-" else "+") ||
	       ::right(::abs(offset) / 3600, 2, "0") ||
	       ::right((::abs(offset) % 3600) / 60, 2, "0")
	    }
	 else {
	    id := a[1]
	    offset := get_known_timezone(id).get_offset() | fail
	    }
	 }
      else {
	 offset := a[1]
	 id := a[2]
	 }
end

procedure init_timezone()
   local s, t1, pat, t2, f, t
   known_timezones := ::table()

   utc_timezone := Timezone(0, "UTC")
   ::insert(known_timezones, "GMT", Timezone(0, "GMT"))
   ::insert(known_timezones, "UTC", utc_timezone)
   ::insert(known_timezones, "UT", Timezone(0, "UT"))
   ::insert(known_timezones, "BST", Timezone(3600, "BST"))
   ::insert(known_timezones, "EST", Timezone(-18000, "EST"))
   ::insert(known_timezones, "EDT", Timezone(-14400, "EDT"))
   ::insert(known_timezones, "CST", Timezone(-21600, "CST"))
   ::insert(known_timezones, "CDT", Timezone(-18000, "CDT"))
   ::insert(known_timezones, "MST", Timezone(-25200, "MST"))
   ::insert(known_timezones, "MDT", Timezone(-21600, "MDT"))
   ::insert(known_timezones, "PST", Timezone(-28800, "PST"))
   ::insert(known_timezones, "PDT", Timezone(-25200, "PDT"))

   #
   # Set the system timezone
   #
   s := ::gettimeofday()[1]
   t1 := util::Time()
   pat := "E MMM dd hh:mm:ss yyyy zzzz"
   t1.parse(ctime(s) || " +0000", pat) | ::stop("Couldn't parse ctime")
   t2 := util::Time()
   t2.parse(gtime(s) || " +0000", pat) | ::stop("Couldn't parse gtime")
   system_timezone := Timezone(t1.get_seconds() - t2.get_seconds())
   # If possible, use a symbolic representation, eg "EST" instead of -0500
   if &features == "UNIX" then {
      if f := ::open("date +%Z", "p") then {
	 t := ::read(f)
	 ::close(f)
	 }
      # Only use a known symbol whose offset agrees with the one just calculated
      if (\known_timezones[\t]).get_offset() = system_timezone.get_offset() then
	 system_timezone := known_timezones[t]
      }
end

procedure get_system_timezone()
   initial {
      init_timezone()
      }
   return system_timezone
end

procedure get_utc_timezone()
   initial {
      init_timezone()
      }
   return utc_timezone
end

#
# Convert a zone id into a Timezone
#
procedure get_known_timezone(id)
   local s, sign
   initial {
      init_timezone()
      }
   if ::member(known_timezones, id) then
      return known_timezones[id]

   id ? {
      if ::any('+-') then {
	 if ::any('-') then
	    sign := -1
	 else
	    sign := 1
	 ::move(1)
	 s := ::tab(::many(&digits)) | fail
	 return Timezone(sign * 3600 * ::integer(s[1:3]) + 60 * ::integer(s[3:5]),
			 id) | fail
	 }
      }
end

This page produced by UniDoc on 2021/04/15 @ 23:59:43.