;+ ; NAME: ; TimeString ; PURPOSE: ; Converts times intro string form ; CATEGORY: ; Tell time ; CALLING SEQUENCE: FUNCTION TimeString, TT , $ ydoy = ydoy , $ ymd = ymd , $ sys = sys , $ vms = vms , $ iso8601 = iso8601 , $ _ymd = _ymd , $ _ydoy = _ydoy , $ from = from , $ upto = upto , $ part = part , $ roundt = roundt , $ format = format ; INPUTS: ; T array; type: time structure ; times to be converted to string form ; OPTIONAL INPUTS: ; /ydoy returns string in form '1999:201:00:00:00.000' ; /ymd returns string in form '1999/11/22 00:00:00.000' ; /sys if set, a PC-style system string is returned (in uppercase) ; /vms if set, a VMS-style system string is returned (in uppercase) ; /iso8601 if set, a ISO-8601 compliant format is used: ; i.e. 2007-01-01T01:01:01.000 ; ; /_ydoy returns string in form 1999_201_000000000' ; /_ymd returns string in form 1999_11_22_000000' ; ; part scalar; type: integer ; same as specifying 'from' and 'upto' with the same argument ; ; from scalar; type: integer ; should be set using the return value of href=TimeUnit=. ; ; If 'format' is NOT set then the time string will start ; at the indicated time unit. ; ; If 'format' is SET then 'from' is ignored. ; ; upto scalar; type: integer ; should be set using the return value of href=TimeUnit=. ; ; If 'format' is NOT set then the time string will end ; indicated time unit. If in addition /roundt is set then ; TT is rounded to unit 'upto' before being turned into a string. ; ; If 'format' is SET, and in addition /roundt is set, then ; 'upto' is used for roundoff only. ; ; format=format ; scalar; type: string; default: none ; string format specifying the time format, e.g. 'YEAR/MN/DD hh:mm:ss.mss' ; The format can combine any of the following sections in any order: ; YEAR insert 4-digit year ; YY insert 2-digit year ; DOY insert day of year ; MON insert month as 3-char string ('jan') ; MN insert month as 2-digit integer (1-12) ; DD insert day of month as 2-digit integer ; DOW insert day of week as 3-char string ('sat') ; hh insert hour of day ; mm insert minutes ; ss insert seconds ; mss,fff insert milliseconds ; OUTPUTS: ; R array; type: string ; times in string form ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; InitVar, IsType, IsTime, TimeGet, TimeUnit, SyncDims ; SEE ALSO: ; TimeSplit ; SIDE EFFECTS: ; An earlier version of TimeString did not have the 'roundt' keyword. ; It would always round when upto was set to units of hours or smaller, ; and not round for units of years or days. ; PROCEDURE: ; If 'format' is NOT set the following formats are supported: ; ; YDOY format: '0000:000:00:00:00.000' (default) ; YMD format: '0000/00/00 00:00:00.000' ; SYS format: 'SAT JAN 10 00:00:00 1991' ; VMS format: '19-NOV-1999 23:48:11.00' ; _YDOY format: '0000_000_000000000' ; _YMD format: '0000_00_00_000000000' ; ; The 'format' keyword obviously is a more transparent way of setting ; a specific time format. The only reason to use one of the specific ; formats above is the 'from' keyword, which is not implemented (yet??) ; for the 'format' keyword (other than explicitly mutilating the ; 'format' itself). ; MODIFICATION HISTORY: ; AUG-1998, Paul Hick (UCSD/CASS) ; NOV-1999, Paul Hick (UCSD/CASS) ; Added VMS keyword ; MAR-2003, Paul Hick (UCSD/CASS) ; Added /fsys keyword ; OCT-2003, Paul Hick (UCSD/CASS) ; Renamed /fsys to /_ydoy. Added /_ymd. ; NOV-2003, Paul Hick (UCSD/CASS) ; Added keyword 'template'. ; JAN-2003, Paul Hick (UCSD/CASS) ; Removed /fsys keyword. ; Added keyword /roundt. Rounding was automatic for 'upto' units ; of hours or smaller. Rounding needs to be specified explicitly ; for all units now. ; OCT-2004, Paul Hick (UCSD/CASS) ; Fixed bug in processing of seconds and msec. If the template ; contained 'hhmmss' to represent hour, minute, seconds then the ; trailing 'mss' would be interpreted as millisecond. This is fixed ; by clearing portion of the template after they have been used. ; JUN-2005, Paul Hick (UCSD/CASS) ; Changed 'template' keyword to 'format'. 'template' is still supported ; (for now). ; JUL-2007, Paul Hick (UCSD/CASS) ; Removed keyword 'template' ; SEP-2007, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; Added keyword /iso8601 to make string in ISO8601-compliant form ;- InitVar, roundt, /key IF IsType(part, /defined) THEN BEGIN from = part upto = part ENDIF CASE IsType(TT,/string) OF 0: T = TT 1: T = TimeSet(TT) END IF roundt AND IsType(upto, /defined) THEN T = TimeGet(T, upto, /roundt) CASE IsType(format,/string) OF 0: BEGIN InitVar, ydoy, /key InitVar, _ydoy, /key InitVar, ymd , /key InitVar, _ymd , /key InitVar, sys , /key InitVar, vms , /key InitVar, iso8601, /key IF ydoy+_ydoy+ymd+_ymd+sys+vms+iso8601 eq 0 THEN ydoy = 1 IF ymd THEN $ ; Format: '0000/00/00 00:00:00.000' C = string(format='(I4.4)',TimeGet(T,TimeUnit(/year))) +'/'+ $ string(format='(I2.2)',TimeGet(T,/month)) +'/'+ $ string(format='(I2.2)',TimeGet(T,/dom )) +' '+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/hour))) +':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/minute)))+':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/sec ))) +'.'+ $ string(format='(I3.3)',TimeGet(T,TimeUnit(/msec))) $ ELSE IF _ymd THEN $ ; Format: '0000_00_00_000000000' C = string(format='(I4.4)',TimeGet(T,TimeUnit(/year))) +'_'+ $ string(format='(I2.2)',TimeGet(T,/month)) +'_'+ $ string(format='(I2.2)',TimeGet(T,/dom )) +'_'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/hour))) + $ string(format='(I2.2)',TimeGet(T,TimeUnit(/minute)))+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/sec ))) + $ string(format='(I3.3)',TimeGet(T,TimeUnit(/msec))) $ ELSE IF ydoy THEN $ ; Format: '0000:000:00:00:00.000' C = string(format='(I4.4)',TimeGet(T,TimeUnit(/year))) +':'+ $ string(format='(I3.3)',TimeGet(T,TimeUnit(/day))) +':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/hour))) +':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/minute)))+':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/sec ))) +'.'+ $ string(format='(I3.3)',TimeGet(T,TimeUnit(/msec))) $ ELSE IF _ydoy THEN $ ; Format: '0000_000_0000000000' C = string(format='(I4.4)',TimeGet(T,timeunit(/year))) +'_'+ $ string(format='(I3.3)',TimeGet(T,TimeUnit(/day))) +'_'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/hour))) + $ string(format='(I2.2)',TimeGet(T,TimeUnit(/minute)))+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/sec ))) + $ string(format='(I3.3)',TimeGet(T,TimeUnit(/msec))) $ ELSE IF sys THEN $ ; Format: 'SAT JAN 10 00:00:00 1991' C = TimeGet(T,/dow)+' '+TimeMonth(TimeGet(T,/month))+' '+ $ string(format='(I2.2)',TimeGet(T,/dom)) +' '+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/hour))) +':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/minute)))+':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/sec))) +' '+ $ string(format='(I4.4)',TimeGet(T,TimeUnit(/year))) $ ELSE IF vms THEN $ ; Format: '10-JAN-1991 00:00:00.00' C = string(format='(I2.2)',TimeGet(T,/dom)) +'-'+ $ TimeMonth(TimeGet(T,/month)) +'-'+ $ string(format='(I4.4)',TimeGet(T,TimeUnit(/year))) +' '+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/hour))) +':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/minute)))+':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/sec))) +'.'+ $ string(format='(I2.2)',round(TimeGet(T,TimeUnit(/msec))/10)) $ ELSE IF iso8601 THEN $ ; Format: '1991-01-10T00:00:00.00' C = string(format='(I4.4)',TimeGet(T,TimeUnit(/year))) +'-'+ $ string(format='(I2.2)',TimeGet(T,/month)) +'-'+ $ string(format='(I2.2)',TimeGet(T,/dom )) +'T'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/hour))) +':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/minute)))+':'+ $ string(format='(I2.2)',TimeGet(T,TimeUnit(/sec))) +'.'+ $ string(format='(I3.3)',TimeGet(T,TimeUnit(/msec))) IF IsType(from, /defined) OR IsType(upto,/defined) THEN BEGIN if IsType(from, /undefined) then from = TimeUnit(/year) if IsType(upto, /undefined) then upto = TimeUnit(/msec) IF ymd THEN BEGIN ;'0000/00/00 00:00:00.000' B = [0,5,11,14,17,20] E = [3,9,12,15,18,22] ENDIF ELSE IF _ymd THEN BEGIN ;'0000/00/00 00:00:00.000' B = [0,5,11,13,15,17] E = [3,9,12,14,16,19] ENDIF ELSE IF _ydoy THEN BEGIN ;'0000_000_000000000' B = [0,5, 9,11,13,15] E = [3,7,10,12,14,17] ENDIF ELSE IF ydoy THEN BEGIN ;'0000:000:00:00:00.000' B = [0,5, 9,12,15,18] E = [3,7,10,13,16,20] ENDIF ELSE IF sys OR vms THEN BEGIN ; Don't extract sub fields from system times B = replicate(0 ,6) E = replicate(strlen(C[0])-1,6) ENDIF C = strmid(C,B[from],E[upto]-B[from]+1) ENDIF END 1: BEGIN ; strput only allows insertions on a string by string basis. ; To avoid a do loop convert the string array to a byte array. C = format IF n_elements(T) EQ 1 then C = [format] ELSE C = replicate(format, n_elements(T) ) C = byte(C) cformat = strlowcase(format) A = strpos(cformat, 'year') IF A EQ -1 THEN A = strpos(cformat, 'yyyy') CASE A EQ -1 OF 0: BEGIN C[A:A+3,*] = byte( string(TimeGet(T,TimeUnit(/year)),format='(I4.4)') ) strput, cformat,' ',A END 1: BEGIN A = strpos(cformat, 'yy') IF A NE -1 THEN BEGIN C[A:A+1,*] = byte( string(TimeGet(T,TimeUnit(/year)) mod 100,format='(I2.2)') ) strput, cformat,' ',A ENDIF END ENDCASE A = strpos(cformat, 'doy') IF A NE -1 THEN BEGIN C[A:A+2,*] = byte( string(TimeGet(T,TimeUnit(/day)),format='(I3.3)') ) strput, cformat,' ',A ENDIF A = strpos(cformat, 'mon') IF A NE -1 THEN BEGIN C[A:A+2,*] = byte( TimeMonth(TimeGet(T,/month)) ) strput, cformat,' ',A ENDIF A = strpos(cformat, 'mn') IF A NE -1 THEN BEGIN C[A:A+1,*] = byte( string(TimeGet(T,/month),format='(I2.2)') ) strput, cformat,' ',A ENDIF A = strpos(cformat, 'dd') IF A NE -1 THEN BEGIN C[A:A+1,*] = byte( string(TimeGet(T,/dom),format='(I2.2)') ) strput, cformat,' ',A ENDIF A = strpos(cformat, 'dow') IF A NE -1 THEN BEGIN C[A:A+2,*] = byte( TimeGet(T,/dow) ) strput, cformat,' ',A ENDIF A = strpos(cformat, 'hh') IF A NE -1 THEN BEGIN C[A:A+1,*] = byte( string(TimeGet(T,TimeUnit(/hour)),format='(I2.2)') ) strput, cformat,' ',A ENDIF A = strpos(cformat, 'mm') IF A NE -1 THEN BEGIN C[A:A+1,*] = byte( string(TimeGet(T,TimeUnit(/minute)),format='(I2.2)') ) strput, cformat,' ',A ENDIF A = strpos(cformat, 'ss') IF A NE -1 THEN BEGIN C[A:A+1,*] = byte( string(TimeGet(T,TimeUnit(/sec)),format='(I2.2)') ) strput, cformat,' ',A ENDIF A = strpos(cformat, 'fff') if A EQ -1 THEN A = strpos(cformat, 'mss') IF A NE -1 THEN BEGIN C[A:A+2,*] = byte( string(TimeGet(T,TimeUnit(/msec)),format='(I3.3)') ) strput, cformat,' ',A ENDIF C = string(C) CASE n_elements(T) EQ 1 OF 0: SyncDims, C, size=size(T) 1: IF n_elements(T) EQ 1 then C = C[0] ENDCASE END ENDCASE RETURN, C & END