Viewing contents of file '../idllib/iuedac/iuelib/pro/dateconv.pro'
;***************************************************************************
;+
;*NAME:
; DATECONV
;
;*CLASS:
; Data Conversion
;
;*CATEGORY:
;
;*PURPOSE:
; Procedure to perform conversion of dates between any of 5 possible
; formats:
; format 1: real*8 scalar encoded as:
; (year-1900)*1000 + day + hour/24. + min/24./60 + sec/24./60/60
; where day is the day of year (1 to 366)
; format 2: Vector encoded as:
; date(0) = year (on output, year will be full year (e.g., 1987)
; but as input, can be specified as 1987 or 87)
; date(1) = day of year (1 to 366)
; date(2) = hour
; date(3) = minute
; date(4) = second
; format 3: string (ascii text) encoded as
; DD-MON-YEAR HH:MM:SS.SS
; (eg. 14-JUL-1987 15:25:44.23)
; Format 3 can also be output in a FITS-compatible format as
; dd/mm/yy (e.g., 22/07/93)
; format 4: three element vector giving spacecraft time words
; from ST telemetry packet.
; format 5: integer number in form yymmdd
;
;*CALLING SEQUENCE:
; DATECONV,DATE,TYPE,OUT
;
;*PARAMETERS:
; DATE (REQ) (I) (0,1) (DSIL)
; input date in one of the allowed formats.
;
; TYPE (REQ) (I) (0) (S)
; type of output format desired.
; valid values:
; 'REAL' - format 1
; 'VECTOR' - format 2
; 'STRING' - format 3
; 'FITS' - modified format 3
; 'INTEGER' - format 5
; TYPE can be abbreviated to the single character strings 'R',
; 'V', 'S', 'F', or 'I'.
; Nobody wants to convert TO spacecraft time (I hope!)
;
; OUT (REQ) (O) (0,1) (BILFDS)
; Converted date in specified format.
;
;*PROCEDURE:
; Input date format is determined using SIZE information.
; Year, day, hour, minute, and second are calculated and reformatted
; as specified by TYPE.
;
;*SYSTEM VARIABLES USED:
;
;*SUBROUTINES CALLED:
; IUEGETTOK - Procedure version of gettok
; PARCHECK
;
;*SIDE EFFECTS:
;
;*RESTRICTIONS:
;
;*PROCEDURE:
;
;*EXAMPLES:
; To generate current date in a format suitable for a FITS keyword:
; dateconv,!stime,'fits',out
;
; To convert 1994 day 152 to yymmdd:
; dateconv,94152.0,'I',out
; out will equal 940601 (i.e., 1994, June 01)
;
;*NOTES:
; Format 3 can be EITHER a string in a format identical to that
; used by IDL system variable !STIME, or that used in FITS headers.
; Format 5 actually produces a longword integer.
;
;*MODIFICATION HISTORY:
; version 1 D. Lindler July, 1987
; adapted for IDL version 2 J. Isensee May, 1990
; 8/06/93 rwt convert function to a procedure, update prolog, use
; IUEGETTOK instead of GETTOK, and add FITS option
; 8/03/94 rwt add format 5 option.
; 11/01/94 rwt fix bug when input date is in format 5
; 11/02/94 rwt allow FITS format strings as input, set internal year
; parameter to be consistently 2 digits (i.e., 92 instead of
; 1992),
; and only use full year in output formats 'R' and 'S'.
; 02/10/95 tmw added check in the interger output block to allow for
; leap years.
;-
;***************************************************************************
pro dateconv,date,type,out
;
npar = n_params()
if npar eq 0 then begin
print,' DATECONV,DATE,TYPE,OUT'
print," where type = 'REAL', 'VECTOR', 'STRING', 'FITS', or 'INTEGER' "
retall & end
parcheck,npar,[2,3],'DATECONV'
;
; data declaration
;
days = [0,31,28,31,30,31,30,31,31,30,31,30,31]
months = [' ','JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT',$
'NOV','DEC']
hour = 0
minute = 0
sec = 0
;
; Determine type of input supplied
;
s = size(date) & ndim = s(0) & datatype = s(ndim+1)
if ndim gt 0 then begin ;vector?
if ndim gt 1 then goto,notvalid
if (s(1) ne 5) and (s(1) ne 3) then goto,notvalid
if (s(1) eq 5) then form = 2 else form = 4
end else begin ;scalar input
case datatype of
0 : goto,notvalid ; undefined
3 : form = 5 ; integer
7 : form = 3 ; string
else: form = 1 ; all else assume numeric scalar
endcase
end
; -----------------------------------
;
;*** convert input to year,day,hour,minute,second
;
; -----------------------------------
case form of
1: begin ;real scalar
idate = long(date)
year = long(idate/1000)
day = idate - year*1000
fdate = date-idate
fdate = fdate*24
hour = fix(fdate)
fdate = (fdate-hour)*60.0
minute = fix(fdate)
sec = float((fdate-minute)*60.0)
end
2: begin ;vector
year = fix(date(0))
year = year - 1900 * (year gt 1900)
day = fix(date(1))
hour = fix(date(2))
minute = fix(date(3))
sec = float(date(4))
end
3: begin ;string
temp = date
stest = strpos(temp,'/',1)
if (stest gt 0) then begin ; FITS format input
iuegettok,temp,'/',day_of_month
iuegettok,temp,'/',mon
iuegettok,temp,'/',year
day = fix(total(days(0:mon-1))+day_of_month)
endif else begin ; IDL format input
iuegettok,temp,'-',day_of_month
iuegettok,temp,'-',month_name
iuegettok,temp,' ',year
year = year - 1900 * (year gt 1900)
iuegettok,temp,':',hour
iuegettok,temp,':',minute
sec = float(strtrim(strmid(temp,0,5)))
;
; convert to day of year from month/day_of_month
; correction for leap years
;
if (fix(year) mod 4) eq 0 then days(2) = 29 ;add 1 to feb
;
; determine month number
;
month_name = strupcase(month_name)
for mon = 1,12 do begin
if month_name eq months(mon) then goto,found
end
print,'DATECONV -- invalid month name specified'
retall
found:
;
; compute day of year
;
day = fix(total(days(0:mon-1))+day_of_month)
endelse
end
4 : begin ;spacecraft time
sc = double(date)
sc = sc + (sc lt 0.0)*65536. ;get rid of neg. numbers
;
; Determine total number of secs since midnight, JAN. 1, 1979
;
secs = sc(2)/64 + sc(1)*1024 + sc(0)*1024*65536.
secs = secs/8192.0d0 ;convert from spacecraft units
;
; Determine number of years
;
mins = secs/60.
hours = mins/60.
totdays = hours/24.
years = totdays/365.
years = fix(years)
;
; Compute number of leap years past
;
leapyears = (years+2)/4
;
; Compute day of year
;
day = fix(totdays-years*365.-leapyears)
;
; Correct for case of being right at end of leapyear
;
if day lt 0 then begin
day = day+366
leapyears = leapyears-1
years = years-1
end
;
; compute hour of day
;
totdays = years*365.+day+leapyears
hour = fix(hours - 24*totdays)
tothours = totdays*24+hour
;
; compute minute
;
minute = fix(mins-tothours*60)
totmin = tothours*60+minute
;
; compute sec
;
sec = secs-totmin*60
;
; compute actual year
;
year = years+79
;
; start day at one and not zero
;
day=day+1
end
5 : begin ;integer time
year = fix(date/10000L)
mon = fix( (date - (year*10000L))/100 )
tday = fix ( date - (year*10000L) - (mon*100) )
if (fix(year) mod 4) eq 0 then days(2) = 29 ;add 1 to feb.
day = fix(total(days(0:mon-1))) + tday
end
endcase
; ---------------------------------------
;
; ***** Now convert to output format
;
; ---------------------------------------
;
; is type a string
;
s = size(type)
if (s(0) ne 0) or (s(1) ne 7) then begin
print,'DATECONV- Output type specification must be a string'
retall
end
;
case strmid(strupcase(type),0,1) of
'V' : begin ;vector output
out = fltarr(5)
year = year + 1900 * (year lt 1900)
out(0) = year
out(1) = day
out(2) = hour
out(3) = minute
out(4) = sec
end
'R' : begin ;floating point scalar
out = sec/24.0d0/60./60. + minute/24.0d0/60. + hour/24.0d0 $
+ day + year*1000d0
end
'S' : begin ;string output
;
; correction for leap years
;
if form ne 3 then $ ;Was it already done?
if (fix(year) mod 4) eq 0 then days(2) = 29
;
; check for valid day
;
if (day lt 1) or (day gt total(days)) then begin
print,'DATE1-- There are only',total(days),' in year ',year
retall
end
;
; find month which day occurs
;
day_of_month = day
month_num = 1
while day_of_month gt days(month_num) do begin
day_of_month = day_of_month - days(month_num)
month_num = month_num+1
end
month_name = months(month_num)
;
; encode into ascii_date
;
year = year+1900
out = string(day_of_month,'(i2)') +'-'+ month_name +'-' + $
string(year,'(i4)') + ' '+ $
string(hour,'(i2)') +':'+ $
strmid(string(minute+100,'(i3)'),1,2) + ':'+ $
strmid(string(sec+100,'(f6.2)'),1,5)
end
'F' : begin ;FITS string output
;
; correction for leap years
;
if form ne 3 then $ ;Was it already done?
if (fix(year) mod 4) eq 0 then days(2) = 29
;
; check for valid day
;
if (day lt 1) or (day gt total(days)) then begin
print,'DATECONV-- There are only',total(days),' in year ',year
retall
end
;
; find month which day occurs
;
day_of_month = day
month_num = 1
while day_of_month gt days(month_num) do begin
day_of_month = day_of_month - days(month_num)
month_num = month_num+1
endwhile
month_name = months(month_num)
;
; encode into ascii_date
;
if (day_of_month lt 10) then $
sdom = '0'+string(day_of_month,'(i1)') else $
sdom = string(day_of_month,'(i2)')
if (month_num lt 10) then $
mn = '0' + string(month_num,'(i1)') else $
mn = string(month_num,'(i2)')
out = sdom + '/' + mn + '/' + string(year,'(i2)')
end
'I' : begin ;Integer output
;
; correction for leap years
;
if form ne 3 then $ ;Was it already done?
if (fix(year) mod 4) eq 0 then days(2) = 29
;
; check for valid day
;
if (day lt 1) or (day gt total(days)) then begin
print,'DATECONV-- There are only',total(days),' in year ',year
retall
end
;
; find month which day occurs
;
day_of_month = day
month_num = 1
while day_of_month gt days(month_num) do begin
day_of_month = day_of_month - days(month_num)
month_num = month_num+1
end
out = (year * 10000L) + (month_num * 100) + day_of_month
end
else: begin ;invalid type specified
print,'DATECONV-- Invalid output type specified'
print,' It must be ''REAL'', ''STRING'', or ''VECTOR'''
retall
end
endcase
return ; dateconv
;
; invalid input date error section
;
notvalid:
print,'DATECONV -- invalid input date specified'
retall
end