When building Report Designer rules there a re a bunch of date/time functions (and others) available in the string conversion functions. Here are some MEDITECH articles that are a great reference when using these functions. I have also included the M-AT source code for these functions. This is helpful in figuring out what arguments need to be setup for these Report Designer functions.
//:Doc Purpose
// This ExternalSubRoutineSet contains many of the adjustment, formatting,
// and conversion utilities for date, time, and datetime data.
//
//:Doc Additional Notes
// All of the utilities in this ExternalSubRoutineSet are documented in the
// M-AT Wiki. Adding any new utilities or functions need to be added to that
// documentation.
//
#Translation
:Options
Result MSFile
Result FSFile
:Product
Type ExternalSubroutineSet
#Preamble
#Magic
:EntryPoint AdjustDate
:EntryPoint ElapsedDates
:EntryPoint ElapsedDatesAsAge
:EntryPoint AgeToBdate
:EntryPoint FormatTime
:EntryPoint FormatDate
:EntryPoint DayOfWeek
:EntryPoint Month
:EntryPoint CreateDateTime
:EntryPoint GetLocalDate
:EntryPoint GetLocalTime
:EntryPoint GetZoneLabel
:EntryPoint AdjustDateTime
:EntryPoint ElapsedDateTimes
:EntryPoint ElapsedDateTimesAsAge
:EntryPoint SecondsToDateTime
:EntryPoint DateTimeToSeconds
:EntryPoint FormatDateTime
:EntryPoint FormatLocalDate
:EntryPoint FormatLocalTime
:EntryPoint CreateDateTimeOt
:EntryPoint DateTimeOtDateOnly
:EntryPoint ExtToIntDateTime
:EntryPoint ExtToIntDateTime5
:EntryPoint ExtToIntDateTimeOt
:EntryPoint CompareAges
:EntryPoint DateLimit
:EntryPoint GmtFromDateTime
:Code AdjustDate
// arg - {YYYYMMDD,value to add,override unit}
@IF{|1@IF{|0="-" ~|0}?"N"@NV "";
|0@CallSub(ValidDate)@NV "";
1 ^{X,A,U}
U|0@UA^U
{X,A}@IF{U="Y" @CallSub(DateAddYears);
U="M" @CallSub(DateAddMonths);
U@{="D",@NV}@! @CallSub(DateAddDays);
1 ""}};
:Code ElapsedDates
// arg - {YYYYMMDD,YYYYMMDD,override unit,override precision}
^{F,T,U,P}
U|0@UA^U
IF{{F,T}@[@CallSub(ValidDate)]@&@NV "";
U@{="D",@NV}@! {T,F}@CallSub(DaysElapsed);
P@CallSub(ValidPrecision)^P@NV "";
U@IF{="Y" 12;="M" 1;1 ""}^U@NV "";
{{F,T},{U,P}}@CallSub(Age)};
:Code ElapsedDatesAsAge
// arg - {YYYYMMDD,YYYYMMDD}
@IF{@CV=1 @{,"T"@ToInternal(DATE)}@JV}
@IF{@[@CallSub(ValidDate)]@&@NV "";
1 @{}@CallSub(Age)};
:Code AgeToBdate
// arg - {YY.MM.DD,YYYYMMDD}
@IF{@CV=1 @{,"T"@ToInternal(DATE)}@JV}
@IF{|0@CallSub(ValidAge)@NV "";
|1@CallSub(ValidDate)@NV "";
1 @{}@CallSub(DateFromAge)};
:Code FormatTime
// arg - {HHMM(SS),override parameter(12, "12C", or 24),display seconds("S" or "SZ"),allow 2400}
^{T,D,S,A},
IF{T@CallSub(ValidTime)@NV "";
D@{@NV,=12,="12C",=24}@!@NV "";
S@{@NV,="S",="SZ"}@!@NV "";
IF{D;@GetStateVariable(ClockFormat)}^D,
{T=2359,A}@& D@IF{=12 "12:00 ed";="12C" "12:00e";1 "24:00"};
(T$2@IF{D$2=12 @IF{=00 12;>12 -12;+0}},
":",T$4%2,
S@IF{="S" T~$4;="SZ" IF{T~$4;00}}@IF{ @(":",)},
IF{D=12 (" ",IF{T$2<12 "a";"p"},"m");
D="12C" IF{T+0=0 "m";IF{T$2=12 T~$2+0=0} "n";T$2<12 "a";"p"}})};
:Code FormatDate
// arg - {YYYYMMDD,format name}
@IF{|0@CallSub(ValidDate)@NV "";
IF{|1;"NUMERIC"}@CallSub(ValidDateFormat)^F@NV "";
F="SPECIAL1" |0@CallSub(FormatDateSpecial1);
F="DAYDATEMONTHYEAR" |0@CallSub(FormatDateDayDateMonthYear);
1 @{|0,F,|1@{#" ",@SV}@<}@CallSub(FormatDateInt)};
:Code DayOfWeek
// arg - {YYYYMMDD,"S" or "L"}
@IF{|0@CallSub(ValidDate)@NV "";
IF{|1|0@UA;"S"}^F~="L"~="S" "";
1 @{@CallList(Days),|0@{$4,$6%2,%2}@DT}@|
@IF{F="S" $3}};
:Code Month
// arg - {YYYYMMDD,"S" or "L"}
@IF{|0@CallSub(ValidDate)@NV "";
IF{|1|0@UA;"S"}^F~="L"~="S" "";
1 @{@CallList(Months),|0$6%2}@|
@IF{F="S" $3}};
:Code CreateDateTime
// arg - {YYYYMMDD,HHMMSS,override time zone,optional "D" or "S" for ambiguous hour,1}
@IF{|0@CallSub(ValidDate)@NV "";
|1@CallSub(ValidTime)@NV "";
|3@UA~="D"~="S" "";
1 @{@(|0,".",|1),|2,|3,|4}@GetDateTimeFromLocal()};
:Code GetLocalDate
// arg - {DateTime,no-op,override zone}
^{D,,Z},
IF{Z {D|0,Z}@GetDateTimeFromGMT()^D},
IF{D@CallSub(ValidDateTime)@NV "";
D|1;
D|0$8};
:Code GetLocalTime
// arg - {DateTime,return seconds("S" or "SZ"),override zone}
^{T,S,Z},
IF{Z {T|0,Z}@GetDateTimeFromGMT()^T},
IF{T@CallSub(ValidDateTime)@NV "";
T|2@NV "";
S@{@NV,="S",="SZ"}@!@NV "";
(T|2,IF{S="S" T|0~$13;S="SZ" IF{T|0~$13;00}})};
:Code GetZoneLabel
// arg - {DateTime}
|0@IF{|3@NV "";
|4 |3@GetTimeZoneDltLabel();
1 |3@GetTimeZoneStdLabel()};
:Code AdjustDateTime
//:Doc Purpose
// Adjust a DateTime by the defined value.
//
//:Doc Arguments
// |0 - X - DateTime
// |1 - A - Value to Add
// |2 - U - Override Unit
//
//:Doc Local Variables
// A - Value to Add
// U - Override Unit
// S - Sign. Either "-" for negative values or "" for positive values
// X - DateTime
//
//:Doc Returns
// Returns an adjusted DateTime. Nil is returned if the Value to Add is not in the correct format.
//
^{X,A,U},
U@UA^U,
IF{A@IF{|0="-" ~|0}
@IF{U="DUR" @ToExternal(DURATION)@Valid(DURATION);
@{,"N"}@?;
1 ""}@NV "";
X|3@GetTimeZoneName()@NV "";
X@CallSub(ValidDateTime)@NV "";
IF{{X}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,DateTimeOtDateOnly) X@{|0,|1,0000,|3,|4}^X},
IF{U="DUR"@NV {{A,U}};
A@CallSub(GetDurAdjList)}
@[^{A,U},
IF{X@NV "";
U|0="Y" X@IF{|1;1 |0$8}@{,A}@CallSub(DateAddYears)
@{@(,".",X@(|2,|0~$13)),X|3,IF{X|4 "D";"S"}}@GetDateTimeFromLocal();
U$2="MO" X@IF{|1;1 |0$8}@{,A}@CallSub(DateAddMonths)
@{@(,".",X@(|2,|0~$13)),X|3,IF{X|4 "D";"S"}}@GetDateTimeFromLocal();
U|0="D" X@IF{|1;1 |0$8}@{,A}@CallSub(DateAddDays)
@{@(,".",X@(|2,|0~$13)),X|3,IF{X|4 "D";"S"}}@GetDateTimeFromLocal();
U|0="H" IF{A|0="-"^S A~|0^A}
X|0$8@IF{A/24>0^D @{,(S,D)}@CallSub(DateAddDays)}
@{@(,".",X|0~$9),(S,A\24+100%2,00)}@CallSub(OffsetTime)
@{,X|3}@CallSub(ComposeFromGmt);
U$2="MI" IF{A|0="-"^S A~|0^A}
X|0$8@IF{A/1440>0^D @{,(S,D)}@CallSub(DateAddDays)}
@{@(,".",X|0~$9),(S,A\1440/60+100%2,A\60+100%2)}@CallSub(OffsetTime)
@{,X|3}@CallSub(ComposeFromGmt);
U@{|0="S",@NV}@! IF{A|0="-"^S A~|0^A}
X|0$8@IF{A/86400>0^D @{,(S,D)}@CallSub(DateAddDays)}
@{@(,".",X|0~$9),(S,A\86400/3600+100%2,A\3600/60+100%2,A\60+100%2)}
@CallSub(OffsetTime)
@{,X|3}@CallSub(ComposeFromGmt);
U="LH" IF{A|0="-"^S A~|0^A}
X@IF{|1;1 |0$8}@IF{A/24>0^D @{,(S,D)}@CallSub(DateAddDays)}
@{@(,".",X@(|2,|0~$13)),(S,A\24+100%2,00)}@CallSub(OffsetTime)
@{,X|3,IF{X|4 "D";"S"},1}@GetDateTimeFromLocal()
@IF{|1="X" |0@{,@{@{X,,"H"}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,ElapsedDateTimes)~=(S,A),"X"}};
1 |0@{,@{@{X,,"H"}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,ElapsedDateTimes)~=(S,A)}@PV}};
1 ""}^X],
X};
:Code GetDurAdjList
//:Doc Purpose
// Get the list adjustment values for a DURATION DataType.
//
//:Doc Arguments
// DURATION value in internal form
//
//:Doc Local Variables
// S - Sign. Either "-" for negative values or "" for positive values
//
//:Doc Returns
// Returns a list of {{NNN,"D"},{NNN,"H"},{NNN,"MI"}} for all entries with an adjustment number
// greater than 0.
//
//:Doc Additional Notes
// Each adjustment value is summed with 0 in order to remove unnecessary zeros from the value.
//
@IF{|0="-"^S ~|0}@AV
@{|0+0@IF{=0 "";@{@(S,),"D"}},
|2+0@IF{=0 "";@{@(S,),"H"}},
|4+0@IF{=0 "";@{@(S,),"MI"}}}@OV;
:Code ElapsedDateTimes
// arg - {DateTime,DateTime,override unit,override precision}
^{F,T,U,P}
U@UA^U
IF{U@{|0="Y",$2="MO",|0="D"}@! {F,T}@[|0$8]@{,{U,P}}@MV@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,ElapsedDates);
{F,T}@[@CallSub(ValidDateTime)]@&@NV "";
{F,T}@[@IF{@{}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,DateTimeOtDateOnly) @{|0,|1,0000,|3,|4}}]^{F,T}
{F,T}@[|0$8]@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,ElapsedDates)^D
{T,F}@[|0~$9@IF{@SV=4 @(,00)}@{$2*3600,$4%2*60,%2}@+]@~-@{,D~*86400}@~+^S
U@{|0="S",@NV}@! S;
P@CallSub(ValidPrecision)^P@NV "";
U@IF{|0="H" 3600;$2="MI" 60;1 ""}^U@NV "";
("S:",P~%1+1,"D")@EV~/U
@IF{P%1="R" ^X("X:",P~%1,"D")@EV;
1 ~%1@IF{%1="." ~%1}}
[P~%1^P]@IF{~+0~=0;P=0;("0.",0:P)}};
:Code ElapsedDateTimesAsAge
// arg - {DateTime,DateTime}
@[|0$8]@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,ElapsedDatesAsAge);
:Code SecondsToDateTime
// arg - {Seconds,override zone}
^{S,Z}
IF{S?"N"@NV "";
{{19800301.000000,Z}@GetDateTimeFromLocal()^A,
{A,S}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,AdjustDateTime)^B}
@[|4]
@IF{@=="+" B;
@PV=@NL B;
={"","+"} {B,0~-3600}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,AdjustDateTime);
={"+",""} {B,3600}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,AdjustDateTime);
1 ""}};
:Code DateTimeToSeconds
// arg - {DateTime,override zone}
^{B,Z}
IF{B@CallSub(ValidDateTime)@NV "";
{19800301.000000,IF{Z;B|3}}@GetDateTimeFromLocal()^A,
{A,B}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,ElapsedDateTimes)^S,
{A,B}@[|4]
@IF{@=="+" S;
@PV=@NL S;
={"","+"} S~+3600;
={"+",""} S~-3600;
1 ""}?"N"};
:Code FormatDateTime
// arg - {DateTime,date format name,zone label flag,
// override parameter(12, "12C", or 24),display seconds("S" or "SZ"),allow 2400}
^{T,F,Z,D,S,A}
IF{{T}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,DateTimeOtDateOnly) @{,F}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,FormatDate);
Z@UA^Z~="Y"~="N" "";
{T}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,GetLocalDate)^X@NV "";
{T,S}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,GetLocalTime)^Y@NV "";
{X,F}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,FormatDate)^X@NV "";
{Y,D,S,A}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,FormatTime)^Y@NV "";
(X," ",Y,{T,Z}@CallSub(TimeZoneDisplay))};
:Code FormatLocalDate
// age - {DateTime,date format name}
^{T,F}
IF{{T}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,GetLocalDate)^X@NV "";
{X,F}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,FormatDate)};
:Code FormatLocalTime
// arg - {DateTime,zone label flag,
// override parameter(12, "12C", or 24),display seconds("S" or "SZ"),allow 2400}
^{T,Z,D,S,A}
IF{Z@UA^Z~="Y"~="N" "";
{T,S}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,GetLocalTime)^Y@NV "";
{Y,D,S,A}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,FormatTime)^Y@NV "";
(Y,{T,Z}@CallSub(TimeZoneDisplay))};
:Code CreateDateTimeOt
// arg - {YYYYMMDD,HHMMSS,override zone,optional "D" or "S" for ambiguous hour,1}
@IF{|1@NV [|4^E]
@{|0,0000,|2}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,CreateDateTime)
@IF{@NV "";
1 @{|0,|1,"",|3,|4}^A,
IF{E {A,""};A}};
1 @CallExternalSub(Mis,MisUtilities.DateTimeGen.C,CreateDateTime)};
:Code DateTimeOtDateOnly
// arg - {DateTime}
|0@IF{@CallSub(ValidDateTime) @IF{|2@NV @IF{|1;1 |0$8};1 ""};
1 ""};
:Code ExtToIntDateTime
// Arguments: {External DateTime,Override Zone}
//
// Variables: E - External DateTime
// Z - Override Zone
//
// Returns: {DateTime,Error} on success, else nil
^{E,Z},
E@SA@UA^E,
IF{E="N" {Z@GetCurrentDateTimeForZone(),""};
{E,Z,"DT"}@CallSub(DateTimeIntConvert)};
:Code ExtToIntDateTime5
// Arguments: {External DateTime,Override Zone}
//
// Variables: E - External DateTime
// Z - Override Zone
//
// Returns: {DateTime,Error} on success, else nil
^{E,Z},
E@SA@UA^E,
{E,Z,"DT5"}@CallSub(DateTimeIntConvert);
:Code ExtToIntDateTimeOt
// Arguments: {External DateTime,Override Zone}
//
// Variables: E - External DateTime
// Z - Override Zone
//
// Returns: {DateTime,Error} on success, else nil
^{E,Z},
E@SA@UA^E,
IF{E="N" {Z@GetCurrentDateTimeForZone(),""};
{E,Z,"DTO"}@CallSub(DateTimeIntConvert)};
:Code CompareAges
// Arguments: {Age1,Age2,Granularity,CompareType}
//
// Variables: A - Age1
// B - Age2
// G - Granularity ("Y" = Years, "MO" = Months, "D" = Days)
// Default is based on youngest age. A<1 = "D", 1<=A<5 = "MO", A>=5 = "Y"
// C - Compare ("E" = equal to, "G" = greater than, "L" = less than,
// "LE" = less than or equal to, "GE" = greater than or equal to)
//
// Returns: Age1 if compare is TRUE, else nil
^{A,B,G,C},
//
// If either age is not a valid internal form, return nil
IF{A@CallSub(ValidAge)@NV "";
B@CallSub(ValidAge)@NV "";
//
// Pad value as necessary for the granularity passed in or default of "D" for days
IF{G@UA;
A&B@AV|0~+0
@IF{<1 "D";
<5 "MO";
1 "Y"}}
@IF{="D" {A,B}@[@AV@(|0:3Z,".",|2:2Z,".",|4:2Z)];
="MO" {A,B}@[@AV@(|0:3Z,".",|2:2Z)];
="Y" {A,B}@[@AV|0:3Z];
1 ""}
//
// Compare Age1 (A) to Age2 (B) using the compare argument or default value of "E"
@IF{@NV "";
C="L" @<;
C="G" @>;
C="LE" @~>;
C="GE" @~<;
C@{="E",@NV}@! @=;
1 ""}
//
// Return A if valued, else nil
IF{ A}};
//-------------------------------------------------------------------
:Code DateLimit
^{M,Y}
M+0^M
IF{M=2 IF{Y\4=0&(Y\100~=0!(Y\400=0)) 29;28};
M~=4~=6~=9~=11 31;30};
:Code DateAddDays
^{X,A}
X$4^Y,
IF{A|0="-" IF{A~|0/146097>0 @{Y,*400}@~-^Y,A~|0\146097@("-",)^A};
IF{A/146097>0 *400+Y^Y,A\146097^A}}
X$6%2^M,
IF{A|0="-" X%2~-(A~|0);
X%2+A}^D
IF{D>28 DO{{M,Y}@CallSub(DateLimit)^L,
D>L M+1^M,D~-L^D,IF{M>12 M~-12^M,Y+1^Y}};
DO{D<1 M~-1^M,IF{M<1 Y~-1^Y,M+12^M},{M,Y}@CallSub(DateLimit)^L,D~+L^D}}
(Y,M+100%2,D+100%2);
:Code DateAddMonths
^{X,A}
X$4^Y,X%2^D,
IF{A|0="-" X$6%2~-(A~|0);
X$6%2+A}^M,
IF{M>12 IF{M\12=0 M/12+Y-1^Y,12^M;
M/12+Y^Y,M\12^M};
M>0;
0~-M^M,
Y~-1~-(M/12)^Y,
12-(M\12)^M}
{Y,M,D}@CallSub(AdjustForEndOfMonth);
:Code DateAddYears
^{X,A}
X$6%2^M,X%2^D,
IF{A|0="-" X$4~-(A~|0);
X$4+A}^Y
{Y,M,D}@CallSub(AdjustForEndOfMonth);
:Code AdjustForEndOfMonth
^{Y,M,D}
{{M,Y}@CallSub(DateLimit),D}@&^D
(Y,M+100%2,D+100%2);
:Code DaysElapsed
[@[$6]@&@IF{%2<03 $4-1;1 $4}/400*400+10000%4^B]
@[@{$4,$6%2,%2}^{Y,M,D}
{Y-B@IF{M<03 -1}@{/4*1461,\4*365}@+,
M+9\12@{/5*153,\5/2*61,\5\2*31}@+,
D}@+
@{,/36525@{/4*3,\4}@+}@-]@~-;
:Code ValidDate
@{?8N,$4+0>0,$6%2+0>0<13,%2+0>0,@{@{$6%2,$4}@CallSub(DateLimit),%2}@~<}@&;
:Code ValidTime
@IF{?6N @{$2<24,$4$2<60,%2<60}@&;?4N @{$2<24,%2<60}@&;1 ""};
:Code ValidAge
@IF{?"N"<151;
@AV@{@QV,@CV=5,@{|1=".",|3="."}@&,@{|0?"N",|2"N",|4"N"}@&}@&;
1 ""};
:Code ValidDateTime
@IF{@QV@NV "";
|0$8@CallSub(ValidDate)@NV "";
|0~$9@CallSub(ValidTime)@NV "";
IF{|2 @CallSub(ValidTime)@NV} "";
|1@NV;
|1@CallSub(ValidDate)@NV "";
1};
:Code ValidPrecision
@UA@IF{@NV "0T";?1N @(,"T");@{="T",="R"}@! @(0,);@{@SV=2,|0?1N,|1@{="T",="R"}@!}@& ;1 ""};
:Code Age
[|0[@IF{|`1,0'@< "-"^S}][@&^F$4^B][@!^T]
IF{{F,T}@[%2]@~> T$6@{%2,$4}@CallSub(DateLimit)^N;
T$6@IF{%2=01 31;1 @{%2-1,$4}@CallSub(DateLimit)}^N
{F%2,T%2,N}@> (F$6,N)^F}
{T,F}@[@{$4-B*12*N,$6%2*N,%2}@+]@-^D]
IF{|1^{U,P} ("D:",P~%1+1,"D")@EV~/(U*N)
@IF{P%1="R" ^X("X:",P~%1,"D")@EV;
1 ~%1@IF{%1="." ~%1}}
[P~%1^P]@IF{~+0~=0;P=0;("0.",0:P)}
@IF{~+0~=0 @(S,)};
1 (S,D/(12*N),".",D\(12*N)/N+100%2,".",D\N+100%2)};
:Code DateFromAge
|0^{A,T},
A@AV@{|0+0^Y,|2+0^M,|4+0^D},
IF{Y>0 {T,("-",Y)}@CallSub(DateAddYears)^T},
IF{D>0 {T,("-",D)}@CallSub(DateAddDays)^T},
IF{M>0 {T,("-",M)}@CallSub(DateAddMonths)^T},
T;
:Code ValidDateFormat
@UA@IF{@NV "";
="DAYDATEMONTHYEAR";
="SPECIAL1";
="LONG" IF{@CallSub(LongFormatOK);
@GetStateVariable(Country)~="US" "D441";
"M441"};
="SHORT" IF{@CallSub(ShortFormatOK);
@GetStateVariable(Country)~="US" "D432";
"M432"};
~="NUMERIC"~="NUMERIC10"~="NUMERIC8" @CallSub(ConvertDateFormat);
[IF{@CallSub(NumericFormatOK);
@GetStateVariable(Country)~="US" "D222";
"M222"}^F]
%2=10 F@(|0,4,%2);
%1=8 F@(|0,2,%2);
1 F};
:Code LongFormatOK
IF{@GetStateVariable(DateFormatLong) @CallSub(ConvertDateFormat)@{="M441",="D441"}@!};
:Code ShortFormatOK
IF{@GetStateVariable(DateFormatShort) @CallSub(ConvertDateFormat)@IF{~|0~=432 ""}};
:Code NumericFormatOK
IF{@GetStateVariable(DateFormatNumeric) @CallSub(ConvertDateFormat)@IF{="M422";
="D422";
="M222";
="D222";
1 ""}};
:Code ConvertDateFormat
@UA@AV@[@IF{?1P "";@QA@WV@NV ""}]@PV
@IF{=@NL "";
@[|0]@CA^O~="YMD"~="DMY"~="MDY" "";
@{,O@{#"Y",#"M",#"D"}}@|@[@SV]@CA^L
~=442~=441~=432~=431~=232~=231~=422~=222 "";
1 (O|0,L)@IF{$2="Y2" ""}};
:Code FormatDateInt
[|0[$4^Y][$6%2^M]%2^D]
[IF{IF{|1|1=2 Y@CallSub(InCentury)} Y%2^Y}]
[@IF{|1|2~=2^A [" "^S]
[@CallList(Months)|M^M]
|1[IF{|2=3 M$3^M}]IF{|3=1 D+0^D};
1 [IF{|2 " ";@GetStateVariable(DateNumericPunctuation)=".";"/"}^S]}]
|1|0@IF{="Y" IF{@GetStateVariable(DateFormatShort)$1="D" (Y,S,D,S,M);
(Y,S,M,S,D)};
="M" (M,S,D,IF{A ","},S,Y);
="D" (D,S,M,S,Y);
1 ""};
:Code InCentury
^Y$3^D,
""@GetCurrentDateTime()@IF{|1;1 |0}$3[-5^L]+4^U,
IF{D&U!L=D Y};
:Code FormatDateSpecial1
@{^D,"Y431"}@CallSub(FormatDateInt)
@IF{{D,"T"@ToInternal(DATE)}@[$4]@= @({D}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,DayOfWeek),~$4)};
:Code FormatDateDayDateMonthYear
@{^D,"D431"}@CallSub(FormatDateInt)
@({D}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,DayOfWeek)," ",);
:Code OffsetTime
//:Doc Purpose
// This code member offsets a time for a give GMT datetime by a number of
// hours, minutes, and/or seconds.
//
//:Doc Arguments
// {T,O}
//
//:Doc Local Variables
// D: Number of days to decrement, specified as a negative number
// H: Hours
// M: Minutes
// O: Amount to offset time in HHMMSS
// S: Seconds
// T: GMT datetime in YYYYMMDD.HHMMSS
//
//:Doc Returns
// Offset GMT datetime in the form YYYYMMDD.HHMMSS.
//
//:Doc Additional Notes
// Real number addition and subtraction are performed in areas where a
// negative number could occur. If the time offset should result in a
// time on the prior day, the current day is decremented by invoking
// DateAddDays with a "-1".
//
^{T,O}
T$11%2^H,T$13%2^M,T~$13^S,
IF{O|0="-" O~|0^O
IF{O@SV=6 S+60-(O%2)
@IF{<60 [M~-1^M];
1 -60}+100%2^S
O$4^O}
M~+60-(O%2)
@IF{<60 [H~-1^H];
1 -60}^M
H~+24-(O$2)
@IF{<24 ["-1"^D];
1 -24}^H;
IF{O@SV=6 S+(O%2)
@IF{<60;
1 [M+1^M]-60}+100%2^S
O$4^O}
M+(O%2)
@IF{<60;
1 [H+1^H]-60}^M
H+(O$2)
@IF{<24;
1 [1^D]-24}^H}
IF{D {T$8,D}@CallSub(DateAddDays);
T$8}
@(,".",H+100%2,M+100%2,S);
:Code ComposeFromGmt
^{G,Z}
IF{{G,Z}@GetTimeOffsetForGmt() [@{G,|0}@CallSub(OffsetTime)^L]
@{G,{L$8,G$8}@~=,L$13%4,Z,|1}};
:Code TimeZoneDisplay
@IF{@IF{|1="N" "";
|1="Y";
@GetStateVariable(TimeZoneDisplay);
|0@{@(@IF{|1;1 |0$8},".",|2),|3}@GetTimeOffsetForLocal()="?";
1 |0@{|3,@GetCurrentTimeZone()}@~=} |0,IF{@{}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,GetZoneLabel) @(" ",)};
1 ""};
:Code GmtFromDateTime
//:Doc Purpose
// Extract GMT date information from a DATETIME object.
//
//:Doc Arguments
// |0: DATETIME
// |1: Granularity Choice:
// "Y": year
// "MO": month
// "D": days
// "H": hours
// "MI": minutes
// "S": seconds
// You can pass granularity text as well such as "YEAR" since only the
// first letter or two is examined.
//
//:Doc Local Variables
// D: DATETIME argument
// G: Granularity (as passed to subroutine)
//
//:Doc Returns
// GMT date time information depending on granularity argument:
// "Y": year - YYYY
// "MO": month - YYYYMM
// "D": day - YYYYMMDD
// "H": hour - YYYYMMDDHH
// "MI": minute - YYYYMMDDHHMM
// "S": second - YYYYMMDDHHMMSS
// Nil is returned if the date is invalid or the granularity is unrecognized.
//
^{D,G},
G@UA
@IF{D@CallSub(ValidDateTime)@NV "";
|0="Y" D|0$4;
$2="MO" D|0$6;
|0="D" D|0$8;
|0="H" D|0@AV@(|0,|2$2);
$2="MI" D|0@AV@(|0,|2$4);
|0="S" D|0@AV@(|0,|2);
1 ""};
:List Days
{Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday}
:List Months
{|January|February|March|April|May|June|July|August|September|October|November|December}
:Code DateTimeIntConvert
// Arguments: {External DateTime,Override Zone,Type}
//
// Variables: E - External DateTime
// Z - Override Zone
// O - Type ("DT", "DT5", or "DTO")
// P - Space Delimiter Location
// D - Date
// T - Time
//
// Returns: {DateTime,Error} on success, else nil
^{E,Z,O},
E#" "^P,
E$P^D,
E~$P@SA@IF{@{%2="AM",%2="PM",%1="A",%1="P"}@! ;
@{@{%2="ED",%1="E"}@!,O="DT5"}@& ;
@{~#" ",@SV}@<^P ~%P}^T,
IF{D@Valid(DATE)@NV "";
IF{O="DT5" T@Valid(HHMM5)@NV;
T @Valid(HHMM)@NV;
O="DTO"@NV} "";
D@ToInternal(DATE)^D,
IF{O="DT5" T@ToInternal(HHMM5);T@ToInternal(HHMM)}^T,
O="DTO" {D,T,Z,"",1}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,CreateDateTimeOt);
{D,T,Z,"",1}@CallExternalSub(Mis,MisUtilities.DateTimeGen.C,CreateDateTime)};