1 Introduction
2 Ground Rules

Building a File System
3 File Systems
4 File Content Data Structure
5 Allocation Cluster Manager
6 Exceptions and Emancipation
7 Base Classes, Testing, and More
8 File Meta Data
9 Native File Class
10 Our File System
11 Allocation Table
12 File System Support Code
13 Initializing the File System
14 Contiguous Files
15 Rebuilding the File System
16 Native File System Support Methods
17 Lookups, Wildcards, and Unicode, Oh My
18 Finishing the File System Class

The Init Program
19 Hardware Abstraction and UOS Architecture
20 Init Command Mode
21 Using Our File System
22 Hardware and Device Lists
23 Fun with Stores: Partitions
24 Fun with Stores: RAID
25 Fun with Stores: RAM Disks
26 Init wrap-up

The Executive
27 Overview of The Executive
28 Starting the Kernel
29 The Kernel
30 Making a Store Bootable
31 The MMC
32 The HMC
33 Loading the components
34 Using the File Processor
35 Symbols and the SSC
36 The File Processor and Device Management
37 The File Processor and File System Management
38 Finishing Executive Startup

Users and Security
39 Introduction to Users and Security
40 More Fun With Stores: File Heaps
41 File Heaps, part 2
42 SysUAF
43 TUser
44 SysUAF API

Terminal I/O
45 Shells and UCL
46 UOS API, the Application Side
47 UOS API, the Executive Side
48 I/O Devices
49 Streams
50 Terminal Output Filters
51 The TTerminal Class
52 Handles
53 Putting it All Together
54 Getting Terminal Input
55 QIO
56 Cooking Terminal Input
57 Putting it all together, part 2
58 Quotas and I/O

UCL
59 UCL Basics
60 Symbol Substitution
61 UCL Command execution
62 UCL Command execution, part 2
63 UCL Command Abbreviation
64 ASTs
65 UCL Expressions, Part 1
66 UCL Expressions, Part 2: Support code
67 UCL Expressions, part 3: Parsing
68 SYS_GETJPIW and SYS_TRNLNM
69 UCL Expressions, part 4: Evaluation

UCL Lexical Functions
70 PROCESS_SCAN
71 PROCESS_SCAN, Part 2
72 TProcess updates
73 Unicode revisted
74 Lexical functions: F$CONTEXT
75 Lexical functions: F$PID
76 Lexical Functions: F$CUNITS
77 Lexical Functions: F$CVSI and F$CVUI
78 UOS Date and Time Formatting
79 Lexical Functions: F$CVTIME
80 LIB_CVTIME
81 Date/Time Contexts
82 SYS_GETTIM, LIB_Get_Timestamp, SYS_ASCTIM, and LIB_SYS_ASCTIM
83 Lexical Functions: F$DELTA_TIME
84 Lexical functions: F$DEVICE
85 SYS_DEVICE_SCAN
86 Lexical functions: F$DIRECTORY
87 Lexical functions: F$EDIT and F$ELEMENT
88 Lexical functions: F$ENVIRONMENT
89 SYS_GETUAI
90 Lexical functions: F$EXTRACT and F$IDENTIFIER
91 LIB_FAO and LIB_FAOL
92 LIB_FAO and LIB_FAOL, part 2
93 Lexical functions: F$FAO
94 File Processing Structures
95 Lexical functions: F$FILE_ATTRIBUTES
96 SYS_DISPLAY
97 UCL Lexical functions: F$GETDVI
98 Parse_GetDVI

Glossary/Index


Download sources
Download binaries

UOS Date and Time Formatting

Before we can move on to the next lexical function, we must discuss UOS date and time formatting. We briefly addressed date/time in our discussion of the Init bootstrap back in article 8. UOS keeps time in the same manner - it is a 64-bit unsigned integer into which is packed the date and time (to the nanosecond). VMS deals with time as 128-bit values, but that provides no benefit over 64-bit values and, in fact, would take extra processing to deal with, so we will differ from VMS in this respect. Remember that a 64-bit integer covers a range of -8,000 BC to 8,000 AD, in one nanosecond increments. However, for reasons of encoding delta times (see below), UOS only deals with integer timestamps greater than 0.

The user can specify UOS Dates in three forms: absolute, delta, and combination.

Absolute Date/Time Format
An absolute date/time indicates a specific date or time of day (or both). The default format is:
{dd-mmm-yyyy}{:}{hh:mm:ss.cc}

The fields are:
FieldMeaning
ddDay of month. An integer from 1 to 31.
mmmMonth of year. One of the following: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC.
yyyyYear. An integer value from 0 to 8000.
hhHour of day. An integer value from 0 to 23.
mmMinute of hour. An integer value from 0 to 59.
ssSecond of minute. An integer value from 0 to 59
ccHundredths of seconds. An integer value from 0 to 99
Note that although UOS keeps track of time to the nanosecond, there is no way to specify a time interval of less than .01 seconds using this format. Also note that even if the hardware that UOS is running on is not able to keep time to this level of resolution, the timestamp value still reserves the space to represent it.

You can also specify an absolute time as one of the following special values.
ValueDefinition
TODAYThe current date at 00:00:00.0 o'clock
TOMORROWTomorrow at 00:00:00.0 o'clock
YESTERDAYYesterday at 00:00:00.0 o'clock

You can abbreviate the date/time as follows.

  • The date or time can be truncated to the right. For instance "28-FEB" or "11:".
  • If you specify both a date and time, they must be separated by a colon.
  • Any field can be null if the delimiters are included.
  • Unspecified date fields default to the appropriate value for the current date.
  • Unspecified time fields default to zero (0).

Examples of abbreviated date/times
SpecificationResult
14-OCTOctober 14 of this year at 00:00:00.0 oo'clock.
11:11:00 today.
10-:3012:30 AM on the 10th day of the current month.
9-00:00:00.0 (12 AM) on the 9th day of the current month.

Delta Date/Time Format
Delta date/time format is an interval relative to the current date and time to a date and time in the past or future. Note that VMS only allows future delta times. In terms of stand-alone delta times, UOS also only supports future delta times. The reason is that delta times are stored as negative values (essentially when the most significant bit is set, it is a delta time). The format is:
+{dddd-}{hh:mm:ss.cc}

The fields are:
FieldMeaning
+This is a plus sign (+) to refer to a future date/time. Include an additional minus sign (-) to refer to a previous date/time.
ddddDays. An integer from 1 to 9999.
hhHours. An integer value from 0 to 23.
mmMinutes. An integer value from 0 to 59.
ssSeconds. An integer value from 0 to 59
ccHundredths of seconds. An integer value from 0 to 99
Delta date/time specifications must start with a plus sign.

You can abbreviate the delta date/time as follows.

  • The time can be truncated to the right. For instance "11:".
  • If you specify both a date and time, they must be separated by a dash.
  • Any field can be null if the delimiters are included.
  • Unspecified time fields default to zero (0).

Combination Date/Time Format
You can combine an ansolute date/time with a delta date/time. The default format is:
{"}{absolute date/time}+delta{"}
{"}{absolute date/time}-delta{"} {"}{absolute date/time}+-delta{"}

the absolute and delta time/date specifications use the same fields and defaults as described above. The one exception is that the delta time/date can start with a minus sign instead of a plus and a minus as long as that is not ambiguous (it can always start with +-). Thus, in combination dates, a delta can be past or future. But you cannot mix plus and negative deltas (such as a negative day with a positive hour) - the entire delta portion of the combination date is either future or past.

The following rules apply:

  • The combination can be enclosed in quotes, but they are not required.
  • The absolute date/time can be omitted to offset the delta from the current date/time. However, if no absolute date/time is specified, past delta date/times must start with the "+-" prefix.

Examples of Combination date/times
Date SpecificationResult
+2Two days from now.
11:-0:29:00 AM today.
31-DEC+::512:05 AM on December 31 of the current year.
1-JAN+-0:2:309:30 PM on December 31 of last year. Note that the +- construct must be used to distinguish between a dash used to delimit month and year from a negative offset.
1-JAN:-0:2:309:30 PM on December 31 of last year. Use of a colon prevents the dash from being interpreted as a delimiter.
+3:0:15Three days and fifteen minutes from now.

Localization
The preceding is fine until you want to deal with dates in a different format. For instance, "2015/12/31" instead of "31-Dec-2015". This is especially true if the UOS user is in a country that has a way of specifying dates that differs from the UOS default. And what of a speaker of another language which has different month names? It becomes even more complicated if there are multiple users of the system that hail from different countries/cultures with different date/time formats. What to do?

The ability of software to be customized to a particular country and/or language is called "Internationalization" (or "I18N" for short). Sometimes it is called "localization", as in "customizing to local conditions". I personally don't care for I18N, and "internationalization" is too long to keep typing, so herein I will use the term "localization".

There are many different aspects of operating system localization. Here we will limit our discussion to that of date/time representation. In future articles we will address other areas of localization. The above discussion describes the default English date format. Why is that the default? Well, simply because that is the language in which I am most proficient. Further, English has become the lingua franca of the modern world - most educated people across all countries in the world speak some form of English. Thus, making English the default for UOS provides the widest possible appeal. But, UOS also provides a means of customizing the system's date/time formats.

The first stage of date localization is to get the default language. The LNM$LANGUAGE symbol is used to define this. SYS$LANGUAGE defaults to "ENGLISH". This value is used for a symbol table name that will be used to determine date formats. Since symbols can be defined locally by a user to override the system symbol of the same name, this allows each user to define his own language rather than use the default defined by SYS$LANGUAGE.

The value of SYS$LANGUAGE is appended to "LNM$LANGUAGE_" to form the name of the symbol table to use for obtaining date formatting information. By default, this means that the table name is "LNM$LANGUAGE_ENGLISH". The values of the symbols in this table are delimited by the first character that occurs in the value. The character must also terminate the values. For instance:
| First-item | Second-item | Third-item |
Note that LIB$DT_INPUT_FORMAT is a single undelimited value.
The LNM$LANGUAGE_* tables each contain the following symbols:
Symbol nameDescription and default valueNumber of elements
LIB$MONTHS_UUppercase month names. Default: "|JANUARY| FEBRUARY| MARCH| APRIL| MAY| JUNE| JULY| AUGUST| SEPTEMBER| OCTOBER| NOVEMBER| DECEMBER|"12
LIB$MONTHS_LLowercase version of LIB$MONTHS_U.12
LIB$MONTHS_CMixed case version of LIB$MONTHS_U.12
LIB$MONTH_ABBREVIATIONS_UUppercase month name abbreviations. Default: "|JAN| FEB| MAR| APR| MAY| JUN| JUL| AUG| SEP| OCT| NOV| DEC|"12
LIB$MONTH_ABBREVIATIONS_LLowercase version of LIB$MONTH_ABBREVIATIONS_U.12
LIB$MONTH_ABBREVIATIONS_CMixed case version of LIB$MONTH_ABBREVIATIONS_U.12
LIB$FORMAT_MNEMONICSMnemonics for formatting date and time. In order, they must be year, numeric month, numeric day, hours, minutes, seconds, fractional seconds, meridium indicator, and alphabetic month. Default: "|YYYY|MM|DD|HH|MM|SS|CC|AM/PM|MONTH|"9
LIB$WEEKDAYS_UUppercase weekday names. Default: "|MONDAY| TUESDAY| WEDNESDAY| THURSDAY| FRIDAY| SATURDAY| SUNDAY|"7
LIB$WEEKDAYS_LLowercase version of LIB$WEEKDAYS_U.7
LIB$WEEKDAYS_CMixed case version of LIB$WEEKDAYS_U.7
LIB$WEEKDAY_ABBREVIATIONS_UUppercase weekday name abbreviations. Default: "|MON| TUE| WED| THU| FRI| SAT| SUN|"7
LIB$WEEKDAY_ABBREVIATIONS_LLowercase version of LIB$WEEKDAY_ABBREVIATIONS_U.7
LIB$WEEKDAY_ABBREVIATIONS_CMixed case version of LIB$WEEKDAY_ABBREVIATIONS_U.7
LIB$RELATIVE_DAYS_UUppercase relative day words. Default: "|YESTERDAY| TODAY| TOMORROW|"3
LIB$RELATIVE_DAYS_LLowercase version of LIB$RELATIVE_DAYS_U.3
LIB$RELATIVE_DAYS_CMixed case version of LIB$RELATIVE_DAYS_U.3
LIB$MI_UUppercase meridium indicators. Default: "|AM|PM|"2
LIB$MI_LLowercase version of LIB$MI_U.2
LIB$MI_CMixed case version of LIB$MI_U.2
LIB$DT_FORMATDate/time output format. Default: "|!DB-!MAAU-!Y4 | !H04:!M0:!S0.!C2|"2
LIB$DT_INPUT_FORMATDate/time input format. Default: "!DB-!MAAU-!Y4:!H04:!M0:!S0.!C2"1

Note that the output format consists of two delimited items: the first is the date format and the second is the time format. During output, these are both used to display the date/time. LIB$DT_FORMAT and LIB$DT_INPUT_FORMAT use special codes that indicate how to format date output (in the former) and the order/type of items during input (the latter). The codes start with an exclamation point (!) and must be one of the following values. Note also that non-space characters that are not part of a code are considered delimiters between the different fields.
CodeDescription
!D0Day, zero-filled
!DDDay, no fill
!DBDay, blank-filled
!WUWeekday, uppercase
!WAUWeekday, abbreviated, capitalized
!WCWeekday, mixed case
!WACWeekday, abbreviated, mixed case
!WLWeekday, lowercase
!WALWeekday, abbreviated, lowercase
!MAUMonth, alphabetic, uppercase
!MAAUMonth, alphabetic, abbreviated, uppercase
!MACMonth, alphabetic, mixed case
!MAACMonth, alphabetic, abbreviated, capitalized
!MALMonth, alphabetic, lowercase
!MAALMonth, alphabetic, abbreviated, lowercase
!MN0Month, numeric, zero-filled
!MNMMonth, numeric, no fill
!MNBMonth, numeric, blank-filled
!Y4Four digit year
!Y3Three digit year
!Y2Two digit year
!Y1One digit year
!Z4Four digit year
!Z3Three digit year
!Z2Two digit year
!Z1One digit year
!H04Hours, zero-filled, 24-hour
!HH4Hours, no fill, 24-hour
!HB4Hours, blank-filled, 24-hours
!H02Hours, zero-filled, 12-hour
!HH2Hours, no fill, 12-hour
!HB2Hours, blank-filled, 12-hour
!M0Minutes, zero-filled
!MMMinutes, no fill
!MBMinutes, blank-filled
!S0Seconds, zero-filled
!SSSeconds, no fill
!SBSeconds, blank-filled
!C77 digit fraction seconds.
!C66 digit fraction seconds.
!C55 digit fraction seconds.
!C44 digit fraction seconds.
!C3Three digit fraction seconds (thousandths).
!C2Double digit fraction seconds (hundreths).
!C1Single digit fraction seconds (tenths).
!MIUMeridium indicator, uppercase
!MICMeridium indicator, mixed case
!MILMeridium indicator, lowercase

To make things more user-friendly, the language tables are pre-defined for UOS. As long as the proper language is set during system installation, most people won't have to worry about the gory details specified above. To further aid the UOS system manager, certain symbol names have been predefined for output date and time formats (this occurs in the system startup command file), as follows:
Symbol nameValueExample output
LIB$DATE_FORMAT_001!DB-!MAAU-!Y417-JAN-2019
LIB$DATE_FORMAT_002!DB !MAU !Y417-JANUARY 2019
LIB$DATE_FORMAT_003!DB.!MAU !Y417.JANUARY 2019
LIB$DATE_FORMAT_004!DB.!MAU.!Y417.JANUARY.2019
LIB$DATE_FORMAT_005!DB !MAU !Y217 JANUARY 19
LIB$DATE_FORMAT_006!DB !MAAU !Y217 JAN 19
LIB$DATE_FORMAT_007!DB.!MAAU !Y217.JAN 19
LIB$DATE_FORMAT_008!DB.!MAAU.!Y217.JAN.19
LIB$DATE_FORMAT_009!DB !MAAU !Y417 JAN 2019
LIB$DATE_FORMAT_010!DB.!MAAU !Y417.JAN 2019
LIB$DATE_FORMAT_011!DB.!MAAU.!Y417.JAN.2019
LIB$DATE_FORMAT_012!MAU !DD, !Y4JANUARY 17, 2019
LIB$DATE_FORMAT_013!MN0/!D0/!Y201/17/19
LIB$DATE_FORMAT_014!MN0-!D0-!Y201-17-19
LIB$DATE_FORMAT_015!MN0.!D0.!Y201.17.19
LIB$DATE_FORMAT_016!MN0 !D0 !Y201 17 19
LIB$DATE_FORMAT_017!D0/!MN0/!Y217/01/19
LIB$DATE_FORMAT_018!D0/!MN0-!Y217/01-19
LIB$DATE_FORMAT_019!D0-!MN0-!Y217-01-19
LIB$DATE_FORMAT_020!D0.!MN0.!Y217.01.19
LIB$DATE_FORMAT_021!D0 !MN0 !Y217 01 19
LIB$DATE_FORMAT_022!Y2/!MN0/!D019/01/17
LIB$DATE_FORMAT_023!Y2-!MN0-!D019-01-17
LIB$DATE_FORMAT_024!Y2.!MN0.!D019.01.17
LIB$DATE_FORMAT_025!Y2 !MN0 !D019 01 17
LIB$DATE_FORMAT_026!Y2!MN0!D0190117
LIB$DATE_FORMAT_027/!Y2.!MN0.!D0/19.01.17
LIB$DATE_FORMAT_028!MN0/!D0/!Y401/17/2019
LIB$DATE_FORMAT_029!MN0-!D0-!Y401-17-2019
LIB$DATE_FORMAT_030!MN0.!D0.!Y401.17.2019
LIB$DATE_FORMAT_031!MN0 !D0 !Y401 17 2019
LIB$DATE_FORMAT_032!D0/!MN0/!Y417/01/2019
LIB$DATE_FORMAT_033!D0-!MN0-!Y417-01-2019
LIB$DATE_FORMAT_034!D0.!MN0.!Y417.01.2019
LIB$DATE_FORMAT_035!D0 !MN0 !Y417 01 2019
LIB$DATE_FORMAT_036!Y4/!MN0/!D02019/01/17
LIB$DATE_FORMAT_037!Y4-!MN0-!D02019-01-17
LIB$DATE_FORMAT_038!Y4.!MN0.!D02019.01.17
LIB$DATE_FORMAT_039!Y4 !MN0 !D02019 01 170
LIB$DATE_FORMAT_040!Y4!MN0!D020190117
LIB$TIME_FORMAT_001!H04:!M0:!S0.!C209:23:34.45
LIB$TIME_FORMAT_002!H04:!M0:!S009:23:34
LIB$TIME_FORMAT_003!H04.!M0.!S009.23.34
LIB$TIME_FORMAT_004!H04 !M0 !S009 23 34
LIB$TIME_FORMAT_005!H04:!M009:23
LIB$TIME_FORMAT_006!H04.!M009.23
LIB$TIME_FORMAT_007!H04 !M009 23
LIB$TIME_FORMAT_008!HH4:!M09:23
LIB$TIME_FORMAT_009!HH4.!M09.23
LIB$TIME_FORMAT_010!HH4 !M09 23
LIB$TIME_FORMAT_011!H02:!M0 !MIU09:23 AM
LIB$TIME_FORMAT_012!HH2:!M0 !MIU9:23 AM
LIB$TIME_FORMAT_013!H04!M00923
LIB$TIME_FORMAT_014!H04H!M0m09H23m
LIB$TIME_FORMAT_015kl !H04.!M0kl 09.23
LIB$TIME_FORMAT_016!H04H!M0'09H23'
LIB$TIME_FORMAT_017!H04.!M0 h09.23 h
LIB$TIME_FORMAT_018h !H04.!M0h 09.23
LIB$TIME_FORMAT_019!HH4 h !MM9 h 23
LIB$TIME_FORMAT_020!HH4 h !MM min !SS s9 h 23 min 34 s

In the next article, we will look at code to parse and manipulate date/time formats.

 

Copyright © 2020 by Alan Conroy. This article may be copied in whole or in part as long as this copyright is included.