PXRMDATE ;SLC/PKR - Clinical Reminders date utilities. ;10/23/2013
;;2.0;CLINICAL REMINDERS;**4,6,12,17,18,24,26**;Feb 04, 2005;Build 404
;
;==================================================
CEFD(FDA) ;Called by the Exchange Utility only if the input packed
;reminder was packed under v1.5. Move Effective Date to Beginning Date.
N IND
S IND=""
F S IND=$O(FDA(811.902,IND)) Q:IND="" D
. I '$D(FDA(811.902,IND,12)) Q
.;If the EFFECTIVE PERIOD exists don't do anything.
. I $D(FDA(811.902,IND,9)) Q
. S FDA(811.902,IND,9)=FDA(811.902,IND,12)
. K FDA(811.902,IND,12)
Q
;
;==================================================
COMPARE(X) ;Compare beginning and ending dates, give a warning if
;Ending Date comes before Beginning Date. Called by ADATE xref in
;definitions and terms.
;Do not execute as part of exchange.
I $G(PXRMEXCH) Q
N BDT,EDT,TEXT
;Dates that are only defined during evaluation, i.e., FIEVAL(2,"DATE")
;cannot be checked here.
S BDT=$S(X(1)'="":$$CTFMD^PXRMDATE(X(1)),1:0)
I BDT=-1 Q
S EDT=X(2)
I EDT="" S EDT="T"
S EDT=$$CTFMD^PXRMDATE(EDT)
I EDT=-1 Q
;If EDT does not contain a time set it to the end of the day.
I EDT'["." S EDT=EDT_".235959"
I EDT<BDT D
. S BDT=$S(X(1)'="":X(1),1:"")
. S EDT=$S(X(2)'="":X(2),1:"T@2400")
. S TEXT="Warning the ending date ("_EDT_") is before the beginning date ("_BDT_")"
. D EN^DDIOL(TEXT)
Q
;
;==================================================
COTN(EFP) ;Convert an Effective Period to the new date/time format.
;Possible effective periods are ND, NM, or NY where N is an integer.
S EFP=$$UP^XLFSTR(EFP)
I (EFP?1N.N1"D")!(EFP?1N.N1"M")!(EFP?1N.N1"Y") D
. S NUM=+EFP
. S EFP=$S(NUM=0:"T",1:"T-"_EFP)
Q EFP
;
;==================================================
CTD(MULT,NUM) ;Convert months or years to days.
N DAYS,INTDAYS,FRAC
S DAYS=MULT*NUM
;Round the number of days.
S INTDAYS=+$P(DAYS,".",1)
S FRAC=DAYS-INTDAYS
S DAYS=$S(FRAC<0.5:INTDAYS,1:INTDAYS+1)
Q DAYS
;
;==================================================
CTFMD(DATE) ;Convert DATE which may be in any of the FileMan acceptable
;forms with additional CR extensions to an internal FileMan date.
N FMDATE,OFFSET,OP,SYM,SYMV,TDATE,TIME
;Already in internal FileMan date format?
I DATE?7N Q DATE
I DATE?7N1"."1.6N Q DATE
S TDATE=$TR(DATE," ",""),TDATE=$$UP^XLFSTR(TDATE)
;Check for T or TODAY with a time.
I $E(TDATE,1)="T" S TIME=$P(TDATE,"@",2),TDATE=$P(TDATE,"@",1)
;Check for dates in the form SYMBOL+IU,or SYMBOL-IU, where I is
;an integer and U is a unit.
S OP=$S(TDATE["+":"+",TDATE["-":"-",1:"")
S SYM=$S(OP'="":$P(TDATE,OP,1),1:TDATE)
S OFFSET=$S(OP'="":$P(TDATE,OP,2),1:"")
;If the symbolic part is not on the list of valid symbols try FileMan.
I '$$VSYM(SYM) D DT^DILF("ST",DATE,.FMDATE) Q FMDATE
;Check for a valid offset.
I OFFSET'="",'$$VOFFSET(OFFSET) Q -1
I ((SYM="T")!(SYM="TODAY")),(OFFSET["H") D Q -1
. I $G(PXRMINTR)=1 D EN^DDIOL("Cannot use "_SYM_" with "_OFFSET)
;If this is being called by the input transform VDT^PXRMINTR we
;are done.
I $G(PXRMINTR)=1 Q 1
;If the symbol is not one of the standard FM symbols then it is
;one of the Clinical Reminder symbols.
S SYMV=$S(SYM="T":$$TODAY,SYM="TODAY":$$TODAY,SYM="N":$$NOW,SYM="NOW":$$NOW,SYM="NOON":$$NOON,SYM="MID":$$MID,1:+$G(@SYM))
I $G(TIME)'="" D
. S SYMV=SYMV_"@"_TIME
. D DT^DILF("ST",SYMV,.FMDATE)
. S SYMV=FMDATE
;If the symbol does not equate to an internal FM date return -1
I '(SYMV?7N0.1"."0.6N) Q -1
Q $$NEWDATE(SYMV,OP,OFFSET)
;
;=================================================
DCHECK(DATE) ;Trap for special characters before calling CTFMD^PXRMDATE.
;Used in DIR("PRE") for date inputs.
I $D(DTOUT) Q DATE
I DATE="" Q DATE
I DATE["^" Q DATE
I DATE["?" Q DATE
Q $$CTFMD^PXRMDATE(DATE)
;
;==================================================
DDATE(DATE) ;Check for an historical (event) date, format as appropriate,
;withou time.
I DATE=0 Q "00/00/0000"
Q $$FMTE^XLFDT(DATE,"5DZ")
;
;==================================================
DUE(DEFARR,RESDATE,FREQ,DUE,DUEDATE,FIEVAL) ;Compute the due date.
;This is the date of the resolution finding + the reminder frequency.
;Subtract the due in advance time to see if the reminder should be
;marked as due soon.
;
N DATE,DIAT,DIATOK,LDATE,PXRMITEM,TDDUE,TODAY
S PXRMITEM=DEFARR("IEN")
;If the final frequency is 0Y then the reminder is not due.
I FREQ="0Y" S DUE=0,DUEDATE="" Q
;
S DUEDATE=""
;Check for custom date due.
I DEFARR(45)'="" S DUEDATE=$$CDUEDATE^PXRMCDUE(.DEFARR,.FIEVAL)
I DUEDATE'="",DUEDATE'=-1 G SETDUE
;
;If there is no resolution logic then frequency is not required.
I (FREQ="")!(FREQ=-1)&(DEFARR(35)'="") D Q
. S ^TMP(PXRMPID,$J,PXRMITEM,"WARNING","NOFREQ")="No reminder frequency - cannot compute due date!"
. S (DUE,DUEDATE)="CNBD"
;
S LDATE=$S(RESDATE["X":0,1:+RESDATE)
I LDATE=0 S (DUE,DUEDATE)="DUE NOW" Q
S DATE=$$FULLDATE(LDATE),DUEDATE=$$NEWDATE(DATE,"+",FREQ)
;
SETDUE ;If the due date is less than or equal to today's date the
;reminder is due.
S TODAY=$$TODAY^PXRMDATE
I +DUEDATE'>TODAY S DUE="DUE NOW" Q
;
S DIAT=$P(DEFARR(0),U,4)
I DIAT="" D
. S DIATOK=0
. S ^TMP(PXRMPID,$J,PXRMITEM,"WARNING","DIAT")="Warning no do in advance time"
E S DIATOK=1
;
S TDDUE=$S(DIATOK=1:$$NEWDATE(DUEDATE,"-",DIAT),1:DUEDATE)
S DUE=$S(TDDUE'>TODAY:"DUE SOON",1:"RESOLVED")
Q
;
;==================================================
DURATION(START,STOP) ;Return the number days between the Start Date and
;Stop Date.
I +START=0 Q 0
N PXRMNOW
S PXRMNOW=$$NOW^PXRMDATE
I START>PXRMNOW Q 0
I (STOP="")!(STOP>PXRMNOW) S STOP=PXRMNOW
Q $$FMDIFF^XLFDT(STOP,START)
;
;==================================================
EDATE(DATE) ;Check for an historical (event) date, format as appropriate,
;include time.
I DATE=0 Q "00/00/0000"
I DATE=-1 Q "None"
Q $$FMTE^XLFDT(DATE,"5Z")
;
;==================================================
FMDATE(DFN,TEST,DATE,VALUE,TEXT) ;FileMan date computed finding.
I TEST="" S TEST=0 Q
S (DATE,VALUE)=$$CTFMD^PXRMDATE(TEST)
S TEST=1
Q
;
;==================================================
FULLDATE(DATE) ;See if DATE is a full date, i.e., it has a month and
;a day along with a year. If the month is missing assume Jan. If the
;day is missing assume the first. Issue a warning so the user knows
;what happened. DATE should be in Fileman format.
N DAY,MISSING,MONTH,TDATE,YEAR
S TDATE=DATE
S MISSING=0
S DAY=$E(DATE,6,7)
S MONTH=$E(DATE,4,5)
S YEAR=$E(DATE,1,3)
I +DAY=0 D
. S DAY=1
. S MISSING=1
. S ^TMP(PXRMPID,$J,PXRMITEM,"INFO","NO DAY")="Encounter date missing the day, using the first for the date due calculation."
I +MONTH=0 D
. S MONTH=1
. S MISSING=1
. S ^TMP(PXRMPID,$J,PXRMITEM,"INFO","NO MONTH")="Encounter date missing the month, using January for the date due calculation."
I MISSING D
. S TDATE=(YEAR*1E4)+(MONTH*1E2)+DAY
. I DATE["E" S TDATE=TDATE_"E"
Q TDATE
;
;==================================================
FRQINDAY(FREQ) ;Given a frequency in the form ND, NM, or NY where N is a
;number and D stands for days, M for months, and Y for years return
;the value in days. Used for ranking only.
I FREQ="" Q 0
N LEN,NUM,UNIT
S NUM=+FREQ
S LEN=$L(FREQ)
S UNIT=$E(FREQ,LEN)
;30.42 is average number of days in a month, 365.24 is average number
;of days in a year. Unknown unit return 0.
S NUM=$S(UNIT="D":NUM,UNIT="M":$$CTD(30.42,NUM),UNIT="Y":$$CTD(365.24,NUM),1:0)
Q NUM
;
;==================================================
ISLEAP(YEAR) ;Given a 3 digit FileMan year return 1 if it is a leap year,
;0 otherwise.
S YEAR=YEAR+1700
Q (YEAR#4=0)&'(YEAR#100=0)!(YEAR#400=0)
;
;==================================================
MCALC(FMDATE,OP,NUM) ;Add or subtract NUM months to FMDATE.
N DAY,DIM,MONTH,TIME,YEAR
S YEAR=$E(FMDATE,1,3),MONTH=$E(FMDATE,4,5),DAY=$E(FMDATE,6,7)
S TIME=$P(FMDATE,".",2)
I TIME'="" S TIME="."_TIME
I OP="+" F Q:'NUM S NUM=NUM-1,MONTH=MONTH+1 I MONTH=13 S YEAR=YEAR+1,MONTH=1
I OP="-" F Q:'NUM S NUM=NUM-1,MONTH=MONTH-1 I MONTH=0 S YEAR=YEAR-1,MONTH=12
S DIM="31^"_($$ISLEAP(YEAR)+28)_"^31^30^31^30^31^31^30^31^30^31"
I DAY>$P(DIM,"^",MONTH) S DAY=$P(DIM,"^",MONTH)
Q YEAR_"00"+MONTH_"00"+DAY_TIME
;
;==================================================
MID() ;If the reminder global PXRMDATE is defined return midnight on that day,
;otherwise return the current date at midnight.
Q $S(+$G(PXRMDATE)>0:$E(PXRMDATE,1,7),1:$$DT^XLFDT)_".24"
;
;==================================================
NEWDATE(FMDATE,OP,OFFSET) ;Given an internal FileMan date, an operator of
;that is + or - ,and an offset of the form I, ID, IW, IM, IY
;where I is a positive integer and H is hours, D is days, W is weeks,
;M is months, and Y is years calculate and return the new FM date.
N DAYS,HOURS,NUM,UNIT
I FMDATE=0 Q 0
S NUM=+OFFSET
I NUM<0 Q -1
S UNIT=$E(OFFSET,$L(NUM)+1)
I UNIT="" S UNIT="D"
I UNIT="H" S HOURS=OP_NUM Q $$FMADD^XLFDT(FMDATE,0,HOURS,0,0)
I UNIT="D" S DAYS=OP_NUM Q $$FMADD^XLFDT(FMDATE,DAYS,0,0,0)
I UNIT="W" S DAYS=OP_(NUM*7) Q $$FMADD^XLFDT(FMDATE,DAYS,0,0,0)
I UNIT="M" Q $$MCALC(FMDATE,OP,NUM)
I UNIT="Y" Q $$YCALC(FMDATE,OP,NUM)
Q -1
;
;==================================================
NOON() ;If the reminder global PXRMDATE is defined return noon on that day,
;otherwise return the current date at noon.
Q $S(+$G(PXRMDATE)>0:$E(PXRMDATE,1,7),1:$$DT^XLFDT)_".12"
;
;==================================================
NOW() ;If the reminder global PXRMDATE is defined return it, otherwise
;return the current date and time.
I +$G(PXRMDATE)=0 Q $$NOW^XLFDT
N NOW,TIME
S TIME=$P(PXRMDATE,".",2)
I TIME="" S TIME=$P($$NOW^XLFDT,".",2),NOW=PXRMDATE_"."_TIME
E S NOW=PXRMDATE
Q NOW
;
;==================================================
TODAY() ;If the reminder global PXRMDATE is defined return it, otherwise
;return the current date.
Q $S(+$G(PXRMDATE)>0:$P(PXRMDATE,".",1),1:$$DT^XLFDT)
;
;==================================================
VDATE(VIEN) ;Given a visit ien return the visit date.
N DATE
S DATE=$S(+VIEN>0:$P($G(^AUPNVSIT(VIEN,0)),U,1),1:0)
I $L(DATE)=0 S DATE=0
;Check for historical encounter.
I $$ISHIST^PXRMVSIT(VIEN) S DATE=DATE_"E"
Q DATE
;
;==================================================
VOFFSET(OFFSET) ;Make sure the offset part of a date is valid. It has to
;have the form I or IU where I is an integer and U is one of the
;following units: H, D, W, M, Y.
I OFFSET?1.N0.1"H"0.1"D"0.1"W"0.1"M"0.1"Y" Q 1
Q 0
;
;==================================================
VSYM(SYM) ;Make sure the symbolic part of a date is valid.
;Already in FileMan internal form.
I SYM?7N Q 1
I SYM?7N1"."1.6N Q 1
;Check for FileMan symbols.
I (SYM="T")!(SYM="TODAY") Q 1
I (SYM="N")!(SYM="NOW") Q 1
I (SYM="NOON") Q 1
I (SYM="MID") Q 1
;Check for Clinical Reminder symbols.
I SYM="PXRMLAD" Q 1
I SYM="PXRMDOB" Q 1
I SYM="PXRMDOD" Q 1
I SYM?1"FIEVAL("1.N1","0.1(1.N1",")1"""DATE"")" Q 1
Q 0
;
;==================================================
YCALC(FMDATE,OP,NUM) ;Add or subtract NUM years to FMDATE.
N DAY,MONTH,TIME,YEAR
S YEAR=$E(FMDATE,1,3),MONTH=$E(FMDATE,4,5),DAY=$E(FMDATE,6,7)
S TIME=$P(FMDATE,".",2)
I TIME'="" S TIME="."_TIME
I OP="+" F Q:'NUM S NUM=NUM-1,YEAR=YEAR+1
I OP="-" F Q:'NUM S NUM=NUM-1,YEAR=YEAR-1
;Handle leap year.
I MONTH="02",DAY>27,'$$ISLEAP(YEAR) S DAY=28
Q YEAR_"00"+MONTH_"00"+DAY_TIME
;
PXRMDATE ;SLC/PKR - Clinical Reminders date utilities. ;10/23/2013
+1 ;;2.0;CLINICAL REMINDERS;**4,6,12,17,18,24,26**;Feb 04, 2005;Build 404
+2 ;
+3 ;==================================================
CEFD(FDA) ;Called by the Exchange Utility only if the input packed
+1 ;reminder was packed under v1.5. Move Effective Date to Beginning Date.
+2 NEW IND
+3 SET IND=""
+4 FOR
SET IND=$ORDER(FDA(811.902,IND))
IF IND=""
QUIT
Begin DoDot:1
+5 IF '$DATA(FDA(811.902,IND,12))
QUIT
+6 ;If the EFFECTIVE PERIOD exists don't do anything.
+7 IF $DATA(FDA(811.902,IND,9))
QUIT
+8 SET FDA(811.902,IND,9)=FDA(811.902,IND,12)
+9 KILL FDA(811.902,IND,12)
End DoDot:1
+10 QUIT
+11 ;
+12 ;==================================================
COMPARE(X) ;Compare beginning and ending dates, give a warning if
+1 ;Ending Date comes before Beginning Date. Called by ADATE xref in
+2 ;definitions and terms.
+3 ;Do not execute as part of exchange.
+4 IF $GET(PXRMEXCH)
QUIT
+5 NEW BDT,EDT,TEXT
+6 ;Dates that are only defined during evaluation, i.e., FIEVAL(2,"DATE")
+7 ;cannot be checked here.
+8 SET BDT=$SELECT(X(1)'="":$$CTFMD^PXRMDATE(X(1)),1:0)
+9 IF BDT=-1
QUIT
+10 SET EDT=X(2)
+11 IF EDT=""
SET EDT="T"
+12 SET EDT=$$CTFMD^PXRMDATE(EDT)
+13 IF EDT=-1
QUIT
+14 ;If EDT does not contain a time set it to the end of the day.
+15 IF EDT'["."
SET EDT=EDT_".235959"
+16 IF EDT<BDT
Begin DoDot:1
+17 SET BDT=$SELECT(X(1)'="":X(1),1:"")
+18 SET EDT=$SELECT(X(2)'="":X(2),1:"T@2400")
+19 SET TEXT="Warning the ending date ("_EDT_") is before the beginning date ("_BDT_")"
+20 DO EN^DDIOL(TEXT)
End DoDot:1
+21 QUIT
+22 ;
+23 ;==================================================
COTN(EFP) ;Convert an Effective Period to the new date/time format.
+1 ;Possible effective periods are ND, NM, or NY where N is an integer.
+2 SET EFP=$$UP^XLFSTR(EFP)
+3 IF (EFP?1N.N1"D")!(EFP?1N.N1"M")!(EFP?1N.N1"Y")
Begin DoDot:1
+4 SET NUM=+EFP
+5 SET EFP=$SELECT(NUM=0:"T",1:"T-"_EFP)
End DoDot:1
+6 QUIT EFP
+7 ;
+8 ;==================================================
CTD(MULT,NUM) ;Convert months or years to days.
+1 NEW DAYS,INTDAYS,FRAC
+2 SET DAYS=MULT*NUM
+3 ;Round the number of days.
+4 SET INTDAYS=+$PIECE(DAYS,".",1)
+5 SET FRAC=DAYS-INTDAYS
+6 SET DAYS=$SELECT(FRAC<0.5:INTDAYS,1:INTDAYS+1)
+7 QUIT DAYS
+8 ;
+9 ;==================================================
CTFMD(DATE) ;Convert DATE which may be in any of the FileMan acceptable
+1 ;forms with additional CR extensions to an internal FileMan date.
+2 NEW FMDATE,OFFSET,OP,SYM,SYMV,TDATE,TIME
+3 ;Already in internal FileMan date format?
+4 IF DATE?7N
QUIT DATE
+5 IF DATE?7N1"."1.6N
QUIT DATE
+6 SET TDATE=$TRANSLATE(DATE," ","")
SET TDATE=$$UP^XLFSTR(TDATE)
+7 ;Check for T or TODAY with a time.
+8 IF $EXTRACT(TDATE,1)="T"
SET TIME=$PIECE(TDATE,"@",2)
SET TDATE=$PIECE(TDATE,"@",1)
+9 ;Check for dates in the form SYMBOL+IU,or SYMBOL-IU, where I is
+10 ;an integer and U is a unit.
+11 SET OP=$SELECT(TDATE["+":"+",TDATE["-":"-",1:"")
+12 SET SYM=$SELECT(OP'="":$PIECE(TDATE,OP,1),1:TDATE)
+13 SET OFFSET=$SELECT(OP'="":$PIECE(TDATE,OP,2),1:"")
+14 ;If the symbolic part is not on the list of valid symbols try FileMan.
+15 IF '$$VSYM(SYM)
DO DT^DILF("ST",DATE,.FMDATE)
QUIT FMDATE
+16 ;Check for a valid offset.
+17 IF OFFSET'=""
IF '$$VOFFSET(OFFSET)
QUIT -1
+18 IF ((SYM="T")!(SYM="TODAY"))
IF (OFFSET["H")
Begin DoDot:1
+19 IF $GET(PXRMINTR)=1
DO EN^DDIOL("Cannot use "_SYM_" with "_OFFSET)
End DoDot:1
QUIT -1
+20 ;If this is being called by the input transform VDT^PXRMINTR we
+21 ;are done.
+22 IF $GET(PXRMINTR)=1
QUIT 1
+23 ;If the symbol is not one of the standard FM symbols then it is
+24 ;one of the Clinical Reminder symbols.
+25 SET SYMV=$SELECT(SYM="T":$$TODAY,SYM="TODAY":$$TODAY,SYM="N":$$NOW,SYM="NOW":$$NOW,SYM="NOON":$$NOON,SYM="MID":$$MID,1:+$GET(@SYM))
+26 IF $GET(TIME)'=""
Begin DoDot:1
+27 SET SYMV=SYMV_"@"_TIME
+28 DO DT^DILF("ST",SYMV,.FMDATE)
+29 SET SYMV=FMDATE
End DoDot:1
+30 ;If the symbol does not equate to an internal FM date return -1
+31 IF '(SYMV?7N0.1"."0.6N)
QUIT -1
+32 QUIT $$NEWDATE(SYMV,OP,OFFSET)
+33 ;
+34 ;=================================================
DCHECK(DATE) ;Trap for special characters before calling CTFMD^PXRMDATE.
+1 ;Used in DIR("PRE") for date inputs.
+2 IF $DATA(DTOUT)
QUIT DATE
+3 IF DATE=""
QUIT DATE
+4 IF DATE["^"
QUIT DATE
+5 IF DATE["?"
QUIT DATE
+6 QUIT $$CTFMD^PXRMDATE(DATE)
+7 ;
+8 ;==================================================
DDATE(DATE) ;Check for an historical (event) date, format as appropriate,
+1 ;withou time.
+2 IF DATE=0
QUIT "00/00/0000"
+3 QUIT $$FMTE^XLFDT(DATE,"5DZ")
+4 ;
+5 ;==================================================
DUE(DEFARR,RESDATE,FREQ,DUE,DUEDATE,FIEVAL) ;Compute the due date.
+1 ;This is the date of the resolution finding + the reminder frequency.
+2 ;Subtract the due in advance time to see if the reminder should be
+3 ;marked as due soon.
+4 ;
+5 NEW DATE,DIAT,DIATOK,LDATE,PXRMITEM,TDDUE,TODAY
+6 SET PXRMITEM=DEFARR("IEN")
+7 ;If the final frequency is 0Y then the reminder is not due.
+8 IF FREQ="0Y"
SET DUE=0
SET DUEDATE=""
QUIT
+9 ;
+10 SET DUEDATE=""
+11 ;Check for custom date due.
+12 IF DEFARR(45)'=""
SET DUEDATE=$$CDUEDATE^PXRMCDUE(.DEFARR,.FIEVAL)
+13 IF DUEDATE'=""
IF DUEDATE'=-1
GOTO SETDUE
+14 ;
+15 ;If there is no resolution logic then frequency is not required.
+16 IF (FREQ="")!(FREQ=-1)&(DEFARR(35)'="")
Begin DoDot:1
+17 SET ^TMP(PXRMPID,$JOB,PXRMITEM,"WARNING","NOFREQ")="No reminder frequency - cannot compute due date!"
+18 SET (DUE,DUEDATE)="CNBD"
End DoDot:1
QUIT
+19 ;
+20 SET LDATE=$SELECT(RESDATE["X":0,1:+RESDATE)
+21 IF LDATE=0
SET (DUE,DUEDATE)="DUE NOW"
QUIT
+22 SET DATE=$$FULLDATE(LDATE)
SET DUEDATE=$$NEWDATE(DATE,"+",FREQ)
+23 ;
SETDUE ;If the due date is less than or equal to today's date the
+1 ;reminder is due.
+2 SET TODAY=$$TODAY^PXRMDATE
+3 IF +DUEDATE'>TODAY
SET DUE="DUE NOW"
QUIT
+4 ;
+5 SET DIAT=$PIECE(DEFARR(0),U,4)
+6 IF DIAT=""
Begin DoDot:1
+7 SET DIATOK=0
+8 SET ^TMP(PXRMPID,$JOB,PXRMITEM,"WARNING","DIAT")="Warning no do in advance time"
End DoDot:1
+9 IF '$TEST
SET DIATOK=1
+10 ;
+11 SET TDDUE=$SELECT(DIATOK=1:$$NEWDATE(DUEDATE,"-",DIAT),1:DUEDATE)
+12 SET DUE=$SELECT(TDDUE'>TODAY:"DUE SOON",1:"RESOLVED")
+13 QUIT
+14 ;
+15 ;==================================================
DURATION(START,STOP) ;Return the number days between the Start Date and
+1 ;Stop Date.
+2 IF +START=0
QUIT 0
+3 NEW PXRMNOW
+4 SET PXRMNOW=$$NOW^PXRMDATE
+5 IF START>PXRMNOW
QUIT 0
+6 IF (STOP="")!(STOP>PXRMNOW)
SET STOP=PXRMNOW
+7 QUIT $$FMDIFF^XLFDT(STOP,START)
+8 ;
+9 ;==================================================
EDATE(DATE) ;Check for an historical (event) date, format as appropriate,
+1 ;include time.
+2 IF DATE=0
QUIT "00/00/0000"
+3 IF DATE=-1
QUIT "None"
+4 QUIT $$FMTE^XLFDT(DATE,"5Z")
+5 ;
+6 ;==================================================
FMDATE(DFN,TEST,DATE,VALUE,TEXT) ;FileMan date computed finding.
+1 IF TEST=""
SET TEST=0
QUIT
+2 SET (DATE,VALUE)=$$CTFMD^PXRMDATE(TEST)
+3 SET TEST=1
+4 QUIT
+5 ;
+6 ;==================================================
FULLDATE(DATE) ;See if DATE is a full date, i.e., it has a month and
+1 ;a day along with a year. If the month is missing assume Jan. If the
+2 ;day is missing assume the first. Issue a warning so the user knows
+3 ;what happened. DATE should be in Fileman format.
+4 NEW DAY,MISSING,MONTH,TDATE,YEAR
+5 SET TDATE=DATE
+6 SET MISSING=0
+7 SET DAY=$EXTRACT(DATE,6,7)
+8 SET MONTH=$EXTRACT(DATE,4,5)
+9 SET YEAR=$EXTRACT(DATE,1,3)
+10 IF +DAY=0
Begin DoDot:1
+11 SET DAY=1
+12 SET MISSING=1
+13 SET ^TMP(PXRMPID,$JOB,PXRMITEM,"INFO","NO DAY")="Encounter date missing the day, using the first for the date due calculation."
End DoDot:1
+14 IF +MONTH=0
Begin DoDot:1
+15 SET MONTH=1
+16 SET MISSING=1
+17 SET ^TMP(PXRMPID,$JOB,PXRMITEM,"INFO","NO MONTH")="Encounter date missing the month, using January for the date due calculation."
End DoDot:1
+18 IF MISSING
Begin DoDot:1
+19 SET TDATE=(YEAR*1E4)+(MONTH*1E2)+DAY
+20 IF DATE["E"
SET TDATE=TDATE_"E"
End DoDot:1
+21 QUIT TDATE
+22 ;
+23 ;==================================================
FRQINDAY(FREQ) ;Given a frequency in the form ND, NM, or NY where N is a
+1 ;number and D stands for days, M for months, and Y for years return
+2 ;the value in days. Used for ranking only.
+3 IF FREQ=""
QUIT 0
+4 NEW LEN,NUM,UNIT
+5 SET NUM=+FREQ
+6 SET LEN=$LENGTH(FREQ)
+7 SET UNIT=$EXTRACT(FREQ,LEN)
+8 ;30.42 is average number of days in a month, 365.24 is average number
+9 ;of days in a year. Unknown unit return 0.
+10 SET NUM=$SELECT(UNIT="D":NUM,UNIT="M":$$CTD(30.42,NUM),UNIT="Y":$$CTD(365.24,NUM),1:0)
+11 QUIT NUM
+12 ;
+13 ;==================================================
ISLEAP(YEAR) ;Given a 3 digit FileMan year return 1 if it is a leap year,
+1 ;0 otherwise.
+2 SET YEAR=YEAR+1700
+3 QUIT (YEAR#4=0)&'(YEAR#100=0)!(YEAR#400=0)
+4 ;
+5 ;==================================================
MCALC(FMDATE,OP,NUM) ;Add or subtract NUM months to FMDATE.
+1 NEW DAY,DIM,MONTH,TIME,YEAR
+2 SET YEAR=$EXTRACT(FMDATE,1,3)
SET MONTH=$EXTRACT(FMDATE,4,5)
SET DAY=$EXTRACT(FMDATE,6,7)
+3 SET TIME=$PIECE(FMDATE,".",2)
+4 IF TIME'=""
SET TIME="."_TIME
+5 IF OP="+"
FOR
IF 'NUM
QUIT
SET NUM=NUM-1
SET MONTH=MONTH+1
IF MONTH=13
SET YEAR=YEAR+1
SET MONTH=1
+6 IF OP="-"
FOR
IF 'NUM
QUIT
SET NUM=NUM-1
SET MONTH=MONTH-1
IF MONTH=0
SET YEAR=YEAR-1
SET MONTH=12
+7 SET DIM="31^"_($$ISLEAP(YEAR)+28)_"^31^30^31^30^31^31^30^31^30^31"
+8 IF DAY>$PIECE(DIM,"^",MONTH)
SET DAY=$PIECE(DIM,"^",MONTH)
+9 QUIT YEAR_"00"+MONTH_"00"+DAY_TIME
+10 ;
+11 ;==================================================
MID() ;If the reminder global PXRMDATE is defined return midnight on that day,
+1 ;otherwise return the current date at midnight.
+2 QUIT $SELECT(+$GET(PXRMDATE)>0:$EXTRACT(PXRMDATE,1,7),1:$$DT^XLFDT)_".24"
+3 ;
+4 ;==================================================
NEWDATE(FMDATE,OP,OFFSET) ;Given an internal FileMan date, an operator of
+1 ;that is + or - ,and an offset of the form I, ID, IW, IM, IY
+2 ;where I is a positive integer and H is hours, D is days, W is weeks,
+3 ;M is months, and Y is years calculate and return the new FM date.
+4 NEW DAYS,HOURS,NUM,UNIT
+5 IF FMDATE=0
QUIT 0
+6 SET NUM=+OFFSET
+7 IF NUM<0
QUIT -1
+8 SET UNIT=$EXTRACT(OFFSET,$LENGTH(NUM)+1)
+9 IF UNIT=""
SET UNIT="D"
+10 IF UNIT="H"
SET HOURS=OP_NUM
QUIT $$FMADD^XLFDT(FMDATE,0,HOURS,0,0)
+11 IF UNIT="D"
SET DAYS=OP_NUM
QUIT $$FMADD^XLFDT(FMDATE,DAYS,0,0,0)
+12 IF UNIT="W"
SET DAYS=OP_(NUM*7)
QUIT $$FMADD^XLFDT(FMDATE,DAYS,0,0,0)
+13 IF UNIT="M"
QUIT $$MCALC(FMDATE,OP,NUM)
+14 IF UNIT="Y"
QUIT $$YCALC(FMDATE,OP,NUM)
+15 QUIT -1
+16 ;
+17 ;==================================================
NOON() ;If the reminder global PXRMDATE is defined return noon on that day,
+1 ;otherwise return the current date at noon.
+2 QUIT $SELECT(+$GET(PXRMDATE)>0:$EXTRACT(PXRMDATE,1,7),1:$$DT^XLFDT)_".12"
+3 ;
+4 ;==================================================
NOW() ;If the reminder global PXRMDATE is defined return it, otherwise
+1 ;return the current date and time.
+2 IF +$GET(PXRMDATE)=0
QUIT $$NOW^XLFDT
+3 NEW NOW,TIME
+4 SET TIME=$PIECE(PXRMDATE,".",2)
+5 IF TIME=""
SET TIME=$PIECE($$NOW^XLFDT,".",2)
SET NOW=PXRMDATE_"."_TIME
+6 IF '$TEST
SET NOW=PXRMDATE
+7 QUIT NOW
+8 ;
+9 ;==================================================
TODAY() ;If the reminder global PXRMDATE is defined return it, otherwise
+1 ;return the current date.
+2 QUIT $SELECT(+$GET(PXRMDATE)>0:$PIECE(PXRMDATE,".",1),1:$$DT^XLFDT)
+3 ;
+4 ;==================================================
VDATE(VIEN) ;Given a visit ien return the visit date.
+1 NEW DATE
+2 SET DATE=$SELECT(+VIEN>0:$PIECE($GET(^AUPNVSIT(VIEN,0)),U,1),1:0)
+3 IF $LENGTH(DATE)=0
SET DATE=0
+4 ;Check for historical encounter.
+5 IF $$ISHIST^PXRMVSIT(VIEN)
SET DATE=DATE_"E"
+6 QUIT DATE
+7 ;
+8 ;==================================================
VOFFSET(OFFSET) ;Make sure the offset part of a date is valid. It has to
+1 ;have the form I or IU where I is an integer and U is one of the
+2 ;following units: H, D, W, M, Y.
+3 IF OFFSET?1.N0.1"H"0.1"D"0.1"W"0.1"M"0.1"Y"
QUIT 1
+4 QUIT 0
+5 ;
+6 ;==================================================
VSYM(SYM) ;Make sure the symbolic part of a date is valid.
+1 ;Already in FileMan internal form.
+2 IF SYM?7N
QUIT 1
+3 IF SYM?7N1"."1.6N
QUIT 1
+4 ;Check for FileMan symbols.
+5 IF (SYM="T")!(SYM="TODAY")
QUIT 1
+6 IF (SYM="N")!(SYM="NOW")
QUIT 1
+7 IF (SYM="NOON")
QUIT 1
+8 IF (SYM="MID")
QUIT 1
+9 ;Check for Clinical Reminder symbols.
+10 IF SYM="PXRMLAD"
QUIT 1
+11 IF SYM="PXRMDOB"
QUIT 1
+12 IF SYM="PXRMDOD"
QUIT 1
+13 IF SYM?1"FIEVAL("1.N1","0.1(1.N1",")1"""DATE"")"
QUIT 1
+14 QUIT 0
+15 ;
+16 ;==================================================
YCALC(FMDATE,OP,NUM) ;Add or subtract NUM years to FMDATE.
+1 NEW DAY,MONTH,TIME,YEAR
+2 SET YEAR=$EXTRACT(FMDATE,1,3)
SET MONTH=$EXTRACT(FMDATE,4,5)
SET DAY=$EXTRACT(FMDATE,6,7)
+3 SET TIME=$PIECE(FMDATE,".",2)
+4 IF TIME'=""
SET TIME="."_TIME
+5 IF OP="+"
FOR
IF 'NUM
QUIT
SET NUM=NUM-1
SET YEAR=YEAR+1
+6 IF OP="-"
FOR
IF 'NUM
QUIT
SET NUM=NUM-1
SET YEAR=YEAR-1
+7 ;Handle leap year.
+8 IF MONTH="02"
IF DAY>27
IF '$$ISLEAP(YEAR)
SET DAY=28
+9 QUIT YEAR_"00"+MONTH_"00"+DAY_TIME
+10 ;