;+ ; NAME: ; timeposn ; PURPOSE: ; Finds location of time in string ; CATEGORY: ; gen/idl/toolbox/time ; CALLING SEQUENCE: FUNCTION timeposn, names_, $ front = front , $ back = back , $ time = time , $ cbreak = cbreak, $ format = format, $ extract = extract,$ part = part , $ length = length ; INPUTS: ; names array; type: string ; strings containing times ; OPTIONAL INPUT PARAMETERS: ; cbreak=cbreak scalar or 2-element array; type: string; default: '_' (underscore) ; separator between time fields. The 2nd, if present is ; used as separator between hrs, min and seconds fields. ; part=part scalar; type: string ; usually part='name'. 'names' is treated as ; a file name and only part 'part' of the name ; is processed (e.g. GetFileSpec(names,part=part) ; only processed the file name part after stripping ; directory and extension) ; /extract return times (i.e. as also returned in keyword 'time') ; OUTPUTS: ; p array; type: long ; position in 'names' where the time starts ; -1 if no time was found ; OPTIONAL OUTPUT PARAMETERS: ; time=time array; type: time structure ; times extracted from 'names'. ; Set to !TheTime if no time was found ; front=front array; type: string ; part of 'names' preceeding the time ; back=back array; type: string ; part of 'names' trailing the time ; format=format array; type: string ; format string used to extract the time with TimeSet ; length=length array; type: integer ; format length, i.e. strlen(format) ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; SyncArgs, InitVar, TimePosn_test, strposn, TimeSet ; PROCEDURE: ; YMD and YDOY type formats are accepted: ; YYYY[_DOY_HHMMSS] and YYYY[_MN_DD_HHMMSS] ; where the parts between brackets are optional. ; ; The date and time of day can be separated by a space (instead ; of a cbreak char. A separate cbreak can be specified for the ; hours, minutes and seconds field (usually a colon). ; IF a millisecond field is present it can be separated from ; the minutes field by a dot. ; EXAMPLE: ; Format YYYY/MN/DD hh:mm:ss.fff is detected with cbreak=['/',':'] ; MODIFICATION HISTORY: ; JUL-2005, Paul Hick (UCSD/CASS) ; DEC-2007, Paul Hick (UCSD/CASS) ; Added /reverse_order to TimePosn_test call that searches ; for the year field. ; MAR-2008, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; Added keywords /extract, part=part and length=length. ; Added code to process cbreak='' (null_string) ;- CASE IsType(part, /defined) OF 0: names = names_ 1: BEGIN names = GetFileSpec(names_, part=part) IF strlowcase(part) EQ 'name' THEN names = GetFileSpec(names, part=part) END ENDCASE back = strlowcase(names) front = '' times = '' format = '' SyncArgs, back, front, times, format InitVar, extract, /key InitVar, cbreak, '_' null_break = cbreak[0] EQ '' IF null_break THEN BEGIN zero = (byte('0'))[0] nine = (byte('9'))[0] FOR i=0L,n_elements(names)-1 DO BEGIN b = byte(back[i]) b = (where(zero LE b AND b LE nine))[0] CASE b OF -1: BEGIN front[i] = back[i] back [i] = '' END 0: ELSE: BEGIN front[i] = strmid(back[i],0,b) back [i] = strmid(back[i],b) END ENDCASE ENDFOR ENDIF ; Look for start of year before first underscore ; The year ends up in 'f' i = n_elements(names) check = lindgen(i) slack = strarr (i) count = 0 REPEAT BEGIN count += 1 ; Break strings at the separator. ; Check the 4-char leading part of the frontend. ; If it is a self-contained 4-char number it must be the year is_too = strposn(back[check],cbreak[0],f,b,/frontdefault,/trailingfront) is_too = TimePosn_test(f,4,cbreak[0],trail,lead, $ complement=is_not,reverse_order=1-null_break,/test_null) IF is_too[0] NE -1 THEN BEGIN ; Year found i = check[is_too] front[i] += lead[is_too] IF null_break THEN BEGIN b[is_too] = trail[is_too]+b[is_too] trail[is_too] = '' ENDIF TimePosn_add, format,times,back,slack,f,b,trail,i,is_too,'YYYY' ENDIF CASE is_not[0] EQ -1 OF ; Year not found (yet) 0: BEGIN i = check[is_not] front[i] += f[is_not] back [i] = b[is_not] check = TimePosn_backcheck(back, i) END 1: check = is_not ENDCASE ENDREP UNTIL check[0] EQ -1 ; OR count gt 10 ; front : prefix before year ; back : postfix after year or is blank check = where(format NE '' AND back NE '') IF check[0] NE -1 THEN BEGIN is_too = strposn(back[check],[cbreak[0],' '],f,b,/frontdefault,/trailingfront) is_too = TimePosn_test(f,3,'',trail,lead,complement=is_not,test_null=null_break) ; Test for day of year IF is_too[0] NE -1 THEN BEGIN cc = check[is_too] IF null_break THEN BEGIN b[is_too] = trail[is_too]+b[is_too] trail[is_too] = '' ENDIF TimePosn_add, format,times,back,slack,f,b,trail,cc,is_too,'DOY' boost, hms_check, cc ENDIF IF is_not[0] NE -1 THEN BEGIN f = f[is_not] b = b[is_not] check = check[is_not] is_too = TimePosn_test(f,2,'',trail,lead) ; Test for month and day of month IF is_too[0] NE -1 THEN BEGIN check = check[is_too] TimePosn_add, format,times,back,slack,f,b,trail,check,is_too,'MN' check = TimePosn_backcheck(back, check) IF check[0] NE -1 THEN BEGIN i = strposn(back[check],[cbreak[0],' '],f,b,/frontdefault,/trailingfront) is_too = TimePosn_test(f,2,'',trail,lead) IF is_too[0] NE -1 THEN BEGIN check = check[is_too] TimePosn_add, format,times,back,slack,f,b,trail,check,is_too,'DD' boost, hms_check, check ENDIF ENDIF ENDIF ENDIF ENDIF CASE IsType(hms_check,/defined) OF 0: check = -1 1: check = TimePosn_backcheck(back, hms_check[sort(hms_check)]) ENDCASE IF check[0] NE -1 THEN BEGIN i = strposn(back[check],cbreak,f,b,/frontdefault,/trailingfront) hms_len = [9,6,4,2] FOR kk=0,n_elements(hms_len)-1 DO BEGIN k = hms_len[kk] IF check[0] NE -1 THEN BEGIN is_too = TimePosn_test(f,k,'',trail,lead,complement=is_not) ; Test for hr,min,sec CASE is_too[0] EQ -1 OF 0: BEGIN cc = check[is_too] TimePosn_add, format,times,back,slack,f,b,trail,cc,is_too,strmid('hhmmssfff',0,k) IF k EQ 2 THEN check = cc END 1: IF k EQ 2 THEN check = is_too ENDCASE IF k NE 2 THEN BEGIN CASE is_not[0] EQ -1 OF 0: BEGIN f = f[is_not] b = b[is_not] check = check[is_not] END 1: check = is_not ENDCASE ENDIF ENDIF ENDFOR ENDIF IF check[0] NE -1 THEN BEGIN hm_break = cbreak[n_elements(cbreak)-1] i = strposn(back[check],hm_break,f,b,/frontdefault,/trailingfront) is_too = TimePosn_test(f,2,'',trail,lead,complement=is_not) IF is_too[0] NE -1 THEN BEGIN check = check[is_too] TimePosn_add, format,times,back,slack,f,b,trail,check,is_too,'mm' check = TimePosn_backcheck(back, check) IF check[0] NE -1 THEN BEGIN i = strposn(back[check],'.',f,b,/frontdefault,/trailingfront) is_too = TimePosn_test(f,2,'',trail,lead) IF is_too[0] NE -1 THEN BEGIN check = check[is_too] TimePosn_add, format,times,back,slack,f,b,trail,check,is_too,'ss' check = TimePosn_backcheck(back, check) IF check[0] NE -1 THEN BEGIN i = strposn(back[check],' ',f,b,/frontdefault,/trailingfront) is_too = TimePosn_test(f,3,'',trail,lead) IF is_too[0] NE -1 THEN BEGIN check = check[is_too] TimePosn_add, format,times,back,slack,f,b,trail,check,is_too,'fff' ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF back = slack+back IF n_elements(names) EQ 1 THEN time = !TheTime ELSE time = replicate(!TheTime,size(names,/dim)) cc = strlen(front) is_too = where(format EQ '', complement=is_not) IF is_too[0] NE -1 THEN cc[is_too] = -1 IF is_not[0] NE -1 THEN BEGIN f = format[is_not] f = f[uniq(f,sort(f))] FOR i=0,n_elements(f)-1 DO BEGIN k = where(format[is_not] EQ f[i]) IF k[0] NE -1 THEN BEGIN k = is_not[k] time[k] = TimeSet(times[k],format=f[i]) ENDIF ENDFOR ENDIF IF extract THEN cc = time length = strlen(format) RETURN, cc & END