Tool 56: Time Tool

Extending the Apple IIGS Toolbox


Development on the Apple IIGS: It's about time

About >

The Time tool set allows GS/OS applications to access the international standard time and date information based on the user's local time zone. This information is especially important for Internet based client and server software for the Apple IIgs. This software is open source using the GNU Public License. License information is found in the Tool56.asm file in the download archive.

The Time Control Panel is provided to let users set their time zone.

Orca/M and REZ is needed to build the software.

References >

Format of ARPA Internet Text Messages: http://www.ietf.org/rfc/rfc822.txt
Interchange of USENET Messages: http://www.ietf.org/rfc/rfc850.txt
Interchange of USENET Messages: http://www.ietf.org/rfc/rfc1036.txt
Application and Support for Internet Hosts: http://www.ietf.org/rfc/rfc1123.txt

asctime(): https://pubs.opengroup.org/onlinepubs/007908799/xsh/asctime.html

Support >

Support for the Time Tool can be found on the ##apple2 irc channel on the irc.libera.chat server.

July 2019: Merlin assembler macros provided. Fixed display of version numbers.

June 2004: Time Tool 56 Version 1.4 released. Rewrote stack code.

April 1999: Time Tool 56 Version 1.3 released. Multiple bugs fixed, including those that can crash the system. Changed license.

Time Tool 56 Version 1.2 not released publicly.

Time Tool 56 Version 1.1 not released publicly.

October 1998: Time Tool 56 Version 1.0 released.

Download >

Apple IIGS Disk Image: tool56.po
Note: Real Apple IIGS users will need to use a utility such as MountIt to access the contents since it can mount disk images.

You may need to set your Web Browser's MIME type to allow download of this file. MIME type is application/vnd.apple2-prodos-disk-image with the extension of "po". This type should always be set to save to disk. Please review your Web Browser's help documentation to set MIME types.

Tool Documentation >

===========================================================================
                            Tool 56 Reference
===========================================================================

$0138 tiBootInit

Initializes the Time Tool Set; called only by the Tool Locator.
Applications must never make this call.

Parameters:

The stack is not effected by this call.  There are no input or output
parameters.

Errors:

None

C

extern pascal void tiBootInit();


$0238 tiStartUp

Starts up the Time Tool Set for use by an application.

Parameters:

The stack is not effected by this call.  There are no input or output
parameters.

Errors:

None

C

extern pascal void tiStartUp();


$0338 tiShutDown

Starts up the Time Tool Set for use by an application.  If your
application has started up the Time Tool Set, the application must
make this call before it quits.

Parameters:

The stack is not effected by this call.  There are no input or output
parameters.

Errors:

None

C

extern pascal void tiShutDown();


$0438 tiVersion

Returns the version number of the Time Tool Set.

Parameters:

Stack Before Call
|________________________________|
|           wordspace            | word -- space for result
|________________________________|
|                                | <- SP

Stack After Call
|________________________________|
|          versionInfo           | word -- version number
|________________________________|
|                                | <- SP

Errors:

None

C

extern pascal Word tiVersion();


$0538 tiReset

Resets up the Time Tool Set; called only when the system is reset.
Applications must never make this call.

Parameters:

The stack is not effected by this call.  There are no input or output
parameters.

Errors:

None

C

extern pascal void tiReset();


$0638 tiStatus

Indicates whether the Time Tool Set is active.  The return value has no
bearing if a zone is available in the preferences.

Parameters:

Stack Before Call
|________________________________|
|           wordspace            | word -- space for result
|________________________________|
|                                | <- SP

Stack After Call
|________________________________|
|          activeFlag            | word -- BOOLEAN; True if tool set is 
|________________________________|         active, false if not.
|                                | <- SP

Errors:

None

C

extern pascal Word tiStatus();


$0938 tiGetTimePrefs

This call returns information that is stored in the TimeTool preference
file.  The return block is sort of similar to the parameter block in GS/OS.
The only difference is that the string is a fixed length field where it is
0 to 5 characters in length based on the return pString length byte.  The
count field specifies how much information is to be returned.  The contents
of the block are: the number of seconds offset from GMT during standard
time, the name of the zone and the Time Zone Control Panel's list item
number.  The latter two values are only used by the Time Zone Control Panel.

Parameters:

Stack Before Call
|________________________________|
|          tiPrefRecPtr          | long -- pointer to space for tiPrefRec
|__                           ___|
|                                |
|________________________________|
|                                | <- SP

Stack After Call
|________________________________|
|                                | <- SP

Errors:

$3801 No local Time Zone.
$3805 Bad Count.

C

extern pascal void tiGetTimePrefs(tiPrefRecPtr);
Long tiPrefRecPtr;

tiPrefRec block
    _______________________
$00|         pCount        | word input value (minimum 1)
   |_______________________|                       
$02|      secOffset        | signed long output value
   |__                  ___|             seconds offset from GMT
   |                       |1
   |_______________________|                       
$06|     tzCPZoneName      | pString output value
   |__                  ___|      name of zone for Time Zone Control Panel
   |                       |
   |__                  ___|2
   |                       |
   |_______________________|                       
$0C|      tzCPRecNum       | word output value
   |_______________________|3     list item for Time Zone Control Panel                       


$0A38 tiSetTimePrefs

Only the Time Zone Control Panel should be making this call.  It sets the
local Time Zone based on setString.  The return block is sort of similar
to the parameter block in GS/OS.  The only difference is that the string
is a fixed length field where it is up to 5 characters in length based on
the pString length byte.  It is suggested that the pString be in the
+/-HHMM differential format, but any of the formats based on the RFCs will
work (note: later RFCs makes some of the earlier formats obsolete and the
obsolete formats will generate error $3802).  The tiCPRecNum and
tzCPZoneName parameters in the tiPrefRec block are used exclusively for the
Time Zone Control Panel.  They keep track of which time zone area was
selected.  If an application is written that needs to use this call,
tiCPRecNum should be set to 0 and tzCPZoneName should be set to a string
that _tiTimeZoneString2Offset accepts.

Parameters:

Stack Before Call
|________________________________|
|          tiPrefRecPtr          | long -- pointer to space for tiPrefRec
|__                           ___|
|                                |
|________________________________|
|                                | <- SP

Stack After Call
|________________________________|
|                                | <- SP

Errors:

$3802 Bad Time Zone string.
$3805 Bad Count.
Any possible GS/OS error from Open or Write GS/OS calls

C

extern pascal void tiSetTimePrefs(tiPrefRecPtr);
Long tiPrefRecPtr;

tiPrefRec block
    _______________________
$00|         pCount        | word input value (minimum 3)
   |_______________________|                       
$02|      secOffset        | signed long output value
   |__                  ___|             seconds offset from GMT
   |                       |1
   |_______________________|                       
$06|     tzCPZoneName      | pString output value
   |__                  ___|      name of zone for Time Zone Control Panel
   |                       |
   |__                  ___|2
   |                       |
   |_______________________|                       
$0C|      tzCPRecNum       | word output value
   |_______________________|3     list item for Time Zone Control Panel                       


$0B38 tiDateString2Sec

This takes an ASCII Date string and determines the number of seconds
it has been since January 1, 1904.  The _ConvSeconds toolbox call is used
and it has an inherent limitation where it can't handle dates beyond 2039.
If there is uncertainty about what value to use for tiParseFlag, it is
recommended that $8000 is used.

Parameters:

Stack Before Call
|________________________________|
|           secondPtr            |long -- pointer to 8 byte space for 
|__                           ___|        for a comp value
|                                |
|________________________________|
|          tiInDatePString       | long -- pointer to valid Date pString
|__                           ___|
|                                |
|________________________________|
|           tiParseFlag          | word -- flag bits specifying how to
|________________________________|         parse the tiInDatePString
|                                | <- SP

Stack After Call
|________________________________|
|                                | <- SP

Errors:

$3801 No local Time Zone.
$3803 Bad Date string.
$3804 Year out of range.
$3807 Invalid parse flags.

C

extern pascal void tiDateString2Sec(secondPtr,tiInDatePString,tiParseFlag);
Long secondPtr;
Long tiInDatePString;
Word tiParseFlag;

tiParseFlag
   bit 15: 1 = 2 digit year assumed to be in 20th/21st century;
           0 = 2 digit year assumed to be in 1st century.
   bit 14: 1 = return $3803 error if day of week is missing;
           0 = day of week in tiInDatePString is optional.
   bit 13: 1 = return $3803 error if zone in RFC822/RFC850 is missing;
           0 = zone in tiInDatePString is optional.
   bit 12: 1 = return $3803 error if zone is not in GMT;
           0 = allow any zone in tiInDatePString.
   bits 9-11: Which formats can tiInDatePString be?
           000 = RFC822, RFC850, and ANSI C's asctime();
           001 = RFC822, RFC850, and hybrids;
           010 = RFC822 and ANSI C's asctime();
           011 = RFC822;
           100 = RFC850 and ANSI C's asctime();
           101 = RFC850;
           110 = ANSI C's asctime();
           111 = Not Valid.
   bit 8:  1 = assume ANSI C's asctime() used local time;
           0 = assume  ANSI C's asctime() used GMT.
   The remaining bits must be set to 0.


$0C38 tiDateString2Epoch

This takes an ASCII Date string and determines the number of seconds
it has been since the UNIX Epoch, January 1, 1970.  The _ConvSeconds
toolbox call is used and it has an inherent limitation where it can't
handle dates beyond 2039.  Dates from 1904 through 1969 will have negative
values for the second from the UNIX epoch.  If there is uncertainty about
what value to use for tiParseFlag, it is recommended that $8000 is used.

Parameters:

Stack Before Call
|________________________________|
|           secondPtr            |long -- pointer to 8 byte space for 
|__                           ___|        for a comp value
|                                |
|________________________________|
|         tiInDatePString        | long -- pointer to valid Date pString
|__                           ___|
|                                |
|________________________________|
|           tiParseFlag          | word -- flag bits specifying how to
|________________________________|         parse the tiInDatePString
|                                | <- SP

Stack After Call
|________________________________|
|                                | <- SP

Errors:

$3801 No local Time Zone.
$3803 Bad Date string.
$3804 Year out of range.
$3807 Invalid parse flags.

C

extern pascal void tiDateString2Epoch(secondPtr,tiInDatePString,tiParseFlag);
Long secondPtr;
Long tiInDatePString;
Word tiParseFlag;

tiParseFlag
   bit 15: 1 = 2 digit year assumed to be in 20th/21st century;
           0 = 2 digit year assumed to be in 1st century.
   bit 14: 1 = return $3803 error if day of week is missing;
           0 = day of week in tiInDatePString is optional.
   bit 13: 1 = return $3803 error if zone in RFC822/RFC850 is missing;
           0 = zone in tiInDatePString is optional.
   bit 12: 1 = return $3803 error if zone is not in GMT;
           0 = allow any zone in tiInDatePString.
   bits 9-11: Which formats can tiInDatePString be?
           000 = RFC822, RFC850, and ANSI C's asctime();
           001 = RFC822, RFC850, and hybrids;
           010 = RFC822 and ANSI C's asctime();
           011 = RFC822;
           100 = RFC850 and ANSI C's asctime();
           101 = RFC850;
           110 = ANSI C's asctime();
           111 = Not Valid.
   bit 8:  1 = assume ANSI C's asctime() uses local time;
           0 = assume  ANSI C's asctime() uses GMT.
   The remaining bits must be set to 0.


$0D38 tiToday2GMTString

A RFC 822 formatted string is constructed based on the time this was called.
The time is presented as Greenwich Mean Time.  The string is a pointer to
space for pString with a length of 36 bytes which includes the length byte.
RFC 822 does not permit years with a length greater than four digits so
this is not a problem.

Parameters:

Stack Before Call
|________________________________|
|        tiOutDatePString        | long -- pointer to space for pString
|__                           ___|
|                                |
|________________________________|
|                                | <- SP

Stack After Call
|________________________________|
|                                | <- SP

Errors:

$3801 No local Time Zone.

C

extern pascal void tiToday2GMTString(tiOutDatePString);
Long tiOutDatePString;


$0E38 tiToday2LocalString

A RFC 822 formatted string is constructed based on the time this was called.
The time zone in the string is based on the local time zone.  The string is
a pointer to space for pString with a length of 38 bytes which includes
the length byte.  RFC 822 does not permit years with a length greater than
four digits so this is not a problem.


Parameters:

Stack Before Call
|________________________________|
|        tiOutDatePString        | long -- pointer to space for pString
|__                           ___|
|                                |
|________________________________|
|                                | <- SP

Stack After Call
|________________________________|
|                                | <- SP

Errors:

$3801 No local Time Zone.

C

extern pascal void tiToday2LocalString(tiOutDatePString);
Long tiOutDatePString;


$0F38 tiParseDateString

This call parses an Internet-based standard Date string and determine
the value of its components.  The following is determined: day of week,
month, day, year, hour, minute, second, and time zone string.  The elements
are stored in a timeGSRec block.  The RFCs do not define how years before
0 are specified so the returned year can never be negative.  However, the
year word is still signed if the RFCs get updated to specify how years
are to be presented before year 0.  The day of week returns the value of 0
if it can not be determined.  Some programs generate the time zone string
in a format such as "-0500 (EST)".  This call will ignore the parentheses
and the text inside it and return only "-0500".  If there is uncertainty
about what value to use for tiParseFlag, it is recommended that $8000
is used.

Stack Before Call
|________________________________|
|          timeGSRecPtr          | long -- pointer to space for TimeGSRec 
|__                           ___|
|                                |
|________________________________|
|         tiInDatePString        | long -- pointer to valid Date pString
|__                           ___|
|                                |
|________________________________|
|           tiParseFlag          | word -- flag bits specifying how to
|________________________________|         parse the tiInDatePString
|                                | <- SP

Stack After Call
|________________________________|
|                                | <- SP

Errors:

$3801 No local Time Zone.
$3803 Bad Date string.
$3804 Year out of range.
$3807 Invalid parse flags.

C

extern pascal void tiParseDateString(timeGSRecPtr,tiInDatePString, tiParseFlag);
Long timeGSRecPtr;
Long tiInDatePString;
Word tiParseFlag;

TimeGSRec block
    _______________________
$00|       dayOfWeek       | word  1 = Sunday ... 7 = Saturday
   |_______________________|                       
$02|         month         | word  0 = January ... 11 = December
   |_______________________|                       
$04|          day          | word  1 ... 31
   |_______________________|                       
$06|          year         | word  -32768 ... 32767
   |_______________________|                       
$08|          hour         | word  0 ... 23
   |_______________________|                       
$0A|         minute        | word  0 ... 59
   |_______________________|                       
$0C|         second        | word  0 ... 59
   |_______________________|                       
$0E|        timeZone       | pstring  time zone string
   |__                  ___|
   |                       |
   |__                  ___|
   |                       |
   |_______________________|                       

tiParseFlag
   bit 15: 1 = 2 digit year assumed to be in 20th/21st century;
           0 = 2 digit year assumed to be in 1st century.
   bit 14: 1 = return $3803 error if day of week is missing;
           0 = day of week in tiInDatePString is optional.
   bit 13: 1 = return $3803 error if zone is missing (in RFC822/RFC850);
           0 = zone in tiInDatePString is optional.
   bit 12: 1 = return $3803 error if zone is not in GMT;
           0 = allow any zone in tiInDatePString.
   bits 9-11: Which formats can tiInDatePString be?
           000 = RFC822, RFC850, and ANSI C's asctime();
           001 = RFC822, RFC850, and hybrids;
           010 = RFC822 and ANSI C's asctime();
           011 = RFC822;
           100 = RFC850 and ANSI C's asctime();
           101 = RFC850;
           110 = ANSI C's asctime();
           111 = Not Valid.
   bit 8:  1 = assume ANSI C's asctime() uses local time;
           0 = assume  ANSI C's asctime() uses GMT.
   The remaining bits must be set to 0.


$1038 tiTimeZoneString2Offset

Given a time zone pString, this will determine the number of seconds offset
from Greenwich Mean Time.

Parameters:

Stack Before Call
|________________________________|
|           secondSpace          | long -- space for result
|__                           ___|
|                                |
|________________________________|
|          tiNamePString         | long -- pointer to pString
|__                           ___|
|                                |
|________________________________|
|                                | <- SP

Stack After Call
|________________________________|
|         offsetSeconds          | signed long -- offset in seconds
|__                           ___|
|                                |
|________________________________|
|                                | <- SP

Errors:

$3802 Bad Time Zone string.

C

extern pascal Long tiTimeZoneString2Offset(tiNamePString);
Long tiNamePString;


$1138 tiOffset2TimeZoneString

Given the number of seconds offset from Greenwich Mean Time, a time zone
pString is returned in +/-HHMM format.  The time zone pString will always
be 6 bytes long including the length byte.  If the seconds offset is not
evenly divisible in minutes, the remaining seconds are ignored--there is
no rounding.  Local daylight savings is taken in consideration for the
generation of the returned string if bit 15 of MangleFlag is set.

Parameters:

Stack Before Call
|________________________________|
|          tiNamePString         | long -- pointer to returned pString
|__                           ___|
|                                |
|________________________________|
|          secondOffset          | signed long -- offset from GMT
|__                           ___|
|                                |
|________________________________|
|            MangleFlag          | word -- flag bits to adjust pString
|________________________________|
|                                | <- SP

Stack After Call
|________________________________|
|                                | <- SP

Errors:

$3806 Seconds offset out of range.

C

extern pascal Long tiOffset2TimeZoneString(tiNamePString,secondOffset, MangleFlag);
Long tiNamePString;
Long secondOffset;
Word MangleFlag;

MangleFlag
   bit 15: 1 = adjust return string for Daylight Savings;
           0 = return string based on the given offset.