Process dates
Info
This how-to assumes you are familiar with setting up a project either manually or via VoltScript Dependency Management. If you are not, follow the Intro to VoltScript Tutorials.
Introduction
LotusScript has always had a date/time Variant (DataType 7). But it doesn't contain a timezone and is unaware of any daylight savings.
When dealing with data in middleware, ISO 8601 is a standard for date/times. But the values are passed in JSON as strings with datetime format. For use within VoltScript, it may be easier to convert to a date object. This is what ZuluVSE provides.
VoltScript dependencies
Incorporating ZuluVSE is straightforward. You just need to add the following JSON object to the vsesDependencies
element in your atlas.json
.
To use the extension in your script, enter UseVSE "*ZuluVSE"
.
Parse dates
The DateTimeParser
class is used to parse a date string or number and return a DateTimeObject
. There are a variety of in-built methods, depending on the value you start with.
Parse ISO dates
ISO dates can be parsed in UTC or with an offset. When dates are in UTC, they don't have an offset but end in "Z". The following code will convert a UTC date-time string to a DateTimeObject:
Function parseISOZuluDateString() as DateTimeObject
Dim dateStr as String
Dim parser as new DateTimeParser()
Dim dateObj as DateTimeObject
dateStr = "2023-08-15T09:50:20Z"
Set dateObj = parser.parseISOString(dateStr)
Return dateObj
End Function
Sometimes a date will be received with an offset. These can also be parsed using parseISOString()
:
Function parseISOOffsetDateString() as DateTimeObject
Dim dateStr as String
Dim parser as new DateTimeParser()
Dim dateObj as DateTimeObject
dateStr = "2023-08-15T02:50:20-07:00"
Set dateObj = parser.parseISOString(dateStr)
Print dateObj.defaultFormat
Return dateObj
End Function
Build from epoch
DateTimeParser.buildDateFromEpoch()
is used to build a DateTimeObject
based on milliseconds since Jan 1 1970 midnight UTC, the Unix epoch. The following code can be used to build a date corresponding to August 15th 2023, 12:08:20 UTC.
Function parseDateEpoch()
Dim parser as new DateTimeParser()
Dim dateObj as DateTimeObject
Set dateObj = parser.BuildDateTimeFromEpoch(1692101300)
Print dateObj.defaultFormat
Return dateObj
End Function
Build from constituent parts
DateTimeParser.buildDateTimeObject()
is used to build a DateTimeObject passing year, month, day, hours, minutes, seconds and offset minutes from UTC. The following code can be used to build a DateTimeObject
for August 4th 2023, 12:20:25 (UTC +01:00).
Function parseDateParts()
Dim parser as new DateTimeParser()
Dim dateObj as DateTimeObject
Set dateObj = parser.BuildDateTimeObject(2023,8,4,11,20,25,-60)
Print dateObj.defaultFormat
Return dateObj
End Function
Build from string with formatting codes
DateTimeParser.ParseDateString()
allows a string date to be parsed with a specific set of format codes for a specific timezone. This function uses formatting codes consistent with the underlying C/C++ format codes.
Formatting DateTimeObjects
Formatting to ISO date format
The basics - using the C/C++ format codes
We use the DateTimeObject.toString()
method to return a date or date/time string formatted to fit our needs. This function uses formatting codes consistent with the underlying C/C++ format codes. Some more common examples are included in the comments of the example code below:
Sub toStringFormatExample()
Dim dtObj as DateTimeObject, dtParser as New DateTimeParser
Dim testISOStr as String, testFmtPattern1 as String, testFmtPattern2 as string, testFmtPattern3 as String
testISOStr = "2023-02-20T20:49:13Z"
testFmtPattern1 = "%Y-%m-%d %H:%M:%S %Z"
testFmtPattern2 = "%F %T %Z"
testFmtPattern3 = "%A, %B %d %Y %T %Z"
Set dtObj = dtParser.ParseISOString(testISOStr)
Print |Using test ISO String "| & testISOStr & |" with no locale code; |
Print |Format pattern "| & testFmtPattern1 & |" returns "| & dtObj.toString(testFmtPattern1, "") & |",|
Print |Format pattern "| & testFmtPattern2 & |" returns "| & dtObj.toString(testFmtPattern2, "") & |",|
Print |Format pattern "| & testFmtPattern3 & |" returns "| & dtObj.toString(testFmtPattern3, "") & |"|
End Sub
In this example code, we have three different formatting patterns to test.
Each of the patterns (testFmtPattern1
, testFmtPattern2
, and testFmtPattern3
) specifies various date time components and the order in which they should appear.
- testFmtPattern1
%Y-%m-%d %H:%M:%S %Z
: This pattern specifies year-month-day hour:minute:second timezone. - testFmtPattern2
%F %T %Z
: This pattern utilizes special shorthand codes.%Y-%m-%d
can be abbreviated to%F
, while%H:%M:%S
can be abbreviated to simply%T
. This pattern therefore also specifies year-month-day hour:minute:second timezone. - testFmtPattern3
%A, %B %d %Y %T %Z
: This pattern demonstrates some additional codes. The day of the week uses the code%A
, and the name of the month uses the code%B
, both of which will be returned in the appropriate language for the locale. This pattern specifies day-of-week, name-of-month day-of-month four-digit-year hour:minute:second timezone.
Common shorthand codes for date/time components
Format code | Description |
---|---|
%B | Full month name |
%b | Abbreviated month name |
%A | Full day name |
%a | Abbreviated day name |
%m | Month |
%d | Day of month |
%0d | Day of month (2 digit) |
%Y | Year as four digits |
%F | Equivalent of %Y-%m-%d |
%H | Hour |
%M | Minute |
%S | Second |
%T | Equivalent of %H:%M:%S |
%Z | Locale-dependent time zone name or abbreviation |
The locale parameter
The locale parameter in DateTimeObject.toString(*format*, *locale*)
allows you to display the names of things like months and days of the week using a country or regionally specific language.
Warning
Before using Locales, you must ensure that the appropriate locale has been installed.
Locale codes consist of appropriate ISO 639 Language Codes and ISO 3166 Country Codes concatenated with an underscore, followed by a period and the encoding format.
Examples:
en_US.utf8
specifies English (United States)es_MX.utf8
specifies Spanish (Mexico)fr_BE.utf8
specifies French (Belgium)
A table of locale codes (less the encoding format) can be found here.
Assuming you were to install locales for both English and French, then using the code "en_US.utf8"
would produce Monday, February 20 2023 20:49:13 UTC
, and "fr_FR.utf8"
would produce lundi, février 20 2023 20:49:13 UTC
.
Info
Using different locales will require the relevant language pack installed on the operating system.
The VoltScript Dev Container is based on Red Hat Enterprise Linux 8 (RHEL 8). This distribution only has a dedicated English langpack for locales, with all others packaged in glibc-all-langpacks
. Installing all locales can be quite large (200+ MB), so glibc-all-langpacks
only installs the locales defined in the build macro _install_langs
to save space.
To select the locales to install:
-
Open a root terminal into the container. See Creating the Dev Container for more details.
-
Edit
/etc/rpm/macros.image-language-conf
to define_install_langs
as the locales you want installed. This is a colon separated list of locale prefixes (ISO 639 Language Codes), for examplede:fr:es
. If a prefix does not contain a_
, it is added. The special argumentall
means to install all locales and must be present by itself. You can change the languages to install with this command, replacing<lang>
with the locales to install: -
Install
glibc-all-langpacks
. This can be done with this command:Locales will be installed to
/usr/lib/locale/locale-archive
. -
Inspect the available locales by running
locale -a
.For more information on selecting what locales to install, run
build-locale-archive -h
after installingglibc-all-langpacks
. This is the tool which compiles the locale archive. The build macro_install_langs
is passed as the argument to--install-langs
.You can change the installed locales by editing
/etc/rpm/macros.image-language-conf
, then reinstallingglibc-all-langpacks
:
Converting LotusScript custom date-time formats
DateTimeParser.ConvertLSFormat()
converts a string of custom LotusScript datetime formats into corresponding C/C++ format codes. The translated formats can now be recognized and used by other ZuluVSE functions, such as ParseDateString()
and toString()
.
Sub Initialize
Dim dtObj as DateTimeObject, dtParser as New DateTimeParser
Dim OldFrmt as String, NewFrmt as String, testFmtLocale as String
Set dtObj = dtParser.GetNow()
testFmtLocale = "C"
OldFrmt = "m/d/yy"
NewFrmt = dtParser.ConvertLSFormat(OldFrmt)
Print "m/d/yy: " & dtObj.toString(NewFrmt, testFmtLocale)
OldFrmt = "d-mmm-yy"
NewFrmt = dtParser.ConvertLSFormat(OldFrmt)
Print "d-mmm-yy: " & dtObj.toString(NewFrmt, testFmtLocale)
OldFrmt = "c"
NewFrmt = dtParser.ConvertLSFormat(OldFrmt)
Print "c: " & NewFrmt & "->" & dtObj.toString(NewFrmt, testFmtLocale)
End Sub
In this example code, 3 custom LotusScript datetime formats are translated.
m/d/yy
is converted into%m/%d/%y
.d-mmm-yy
is converted into%d-%b-%y
.c
is converted into%m/%d/%y %H:%M:%S
.
Custom LotusScript datetime formats and their respective C/C++ format equivalents
LotusScript | C/C++ |
---|---|
c | %m/%d/%y %H:%M:%S |
d | %d |
dd | %d |
ddd | %a |
dddd | %A |
ddddd | %m/%d/%y |
dddddd | %B %d, %Y |
w | %w |
ww | %V |
m | %m |
mm | %m |
mmm | %b |
mmmm | %B |
y | %j |
yy | %y |
yyyy | %Y |
h | %H |
hh | %H |
n | %M |
nn | %M |
s | %S |
ss | %S |
ttttt | %H:%M:%S |
AM/PM am/pm | %p |
A/P a/p | %p |
z | %z |
zz | %Z |
Info
Since LotusScripts doesnt have formats for writing locales, We've added z
and zz
for that purpose. z
writes locale-dependent time zone name or abbreviation while zz
writes offset from UTC in the ISO 8601 format (e.g. -0430).