// IfsTimeIO.bcpl
// Copyright Xerox Corporation 1979, 1980, 1981

// Last modified November 18, 1981  5:08 PM by Taft

// Functional replacement for:
// TimeIO.bcpl -- conversion between unpacked internal representation
//		and external (printed) form -- from Time package

get "Ifs.decl"
get "Time.d"

//	WRITEUDT(strm, uvec [, printZone])
// writes the unpacked date and time from uvec onto the
// stream strm in the form 29-DEC-74 14:43:37.  If uvec=0,
// uses the current date and time.  If printZone is supplied and true,
// appends the time zone to the result, e.g., " PDT" or " +03" or "-02:30".

//	WritePackedDT(strm, pvec)
// similar to WRITEUDT except accepts packed rather than unpacked time.

//	FINDMONTH(strg)
// returns the month number (0-11) for the month whose name
// is strg (may be a prefix), or -1 if not a month name.

//	MONTHNAME(mo)
// returns the name of month number mo.


external	// procedures defined
[
// outgoing procedures
WRITEUDT
WritePackedDT
FINDMONTH
MONTHNAME

// incoming procedures
UNPACKDT
PACKDT
MoveBlock
PutTemplate
Wss
Max
StringCompare

// outgoing statics
monthNames
]

static [ monthNames ]

manifest signShift = 16 - (offset UTV.zone.sign + size UTV.zone.sign) rem 16
manifest hourShift = 16 - (offset UTV.zone.hour + size UTV.zone.hour) rem 16

//----------------------------------------------------------------------------
let WRITEUDT(strm, uvec, printZone; numargs na) = valof
//----------------------------------------------------------------------------
[
let ucur = vec 6
if uvec eq 0 then [ UNPACKDT(0, ucur); uvec = ucur ]

// trim month name to 3 characters
let month = vec 2
MoveBlock(month, MONTHNAME(uvec>>UTV.month), 2)
month>>String.length = 3

PutTemplate(strm, "$2D-$S-$2F0D $2D:$2F0D:$2F0D",
 uvec>>UTV.day, month, uvec>>UTV.year rem 100,
 uvec>>UTV.hour, uvec>>UTV.minute, uvec>>UTV.second)

if na ge 3 & printZone then
   switchon uvec>>UTV.zone into
      [
      case 4 lshift hourShift:
      case 5 lshift hourShift:
      case 6 lshift hourShift:
      case 7 lshift hourShift:
      case 8 lshift hourShift:
      case 9 lshift hourShift:
      case 10 lshift hourShift:
         PutTemplate(strm, " $C$CT",
          "AECMPYH">>String.char↑(uvec>>UTV.zone.hour-3),
          (uvec>>UTV.daylight? $D, $S))
         endcase
      case 0: case 1 lshift signShift:  // zero may be + or -
         unless uvec>>UTV.daylight do  // daylight falls thru to default case
            [ Wss(strm, " GMT"); endcase ]
      default:
         let h = uvec>>UTV.zone.hour
         if uvec>>UTV.zone.sign then h = -h
         if uvec>>UTV.daylight then h = h-1
         PutTemplate(strm, " $C$2F0D", (h ls 0? $-, $+), Max(h, -h))
         if uvec>>UTV.zone.minute ne 0 then
            PutTemplate(strm, ":$2F0D", uvec>>UTV.zone.minute)
         endcase
      ]
]

//----------------------------------------------------------------------------
and WritePackedDT(str, time) be
//----------------------------------------------------------------------------
[
let uv = vec 6
UNPACKDT(time, uv)
WRITEUDT(str, uv)
]

//----------------------------------------------------------------------------
and MONTHNAME(mo) = monthNames+mo*5
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
and FINDMONTH(strg) = valof
//----------------------------------------------------------------------------
[
if strg>>String.length ls 3 resultis -1
for j = 0 by 5 to 55 do
   [
   let match = StringCompare(strg, monthNames+j)
   if match eq 0 % match eq -2 resultis j/5  // exact or initial substring
   ]
resultis -1
]