go_date.F90 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598
  1. !###############################################################################
  2. !
  3. ! go_date - module to manipulate date structures
  4. !
  5. ! TYPES
  6. !
  7. ! A structure is provided to store a date:
  8. !
  9. ! ! declare date types:
  10. ! type(TDate) :: t0, t1, t, dt
  11. !
  12. ! with fields:
  13. !
  14. ! character(len=4) :: calender ! see 'CALENDERS'
  15. !
  16. ! integer :: year, month, day, hour, min, sec, mili
  17. !
  18. ! integer :: zone ! minutes; add this to obtain GMT
  19. !
  20. !
  21. ! CALENDERS
  22. !
  23. ! A number of different calender types is supported:
  24. !
  25. ! 'wall' : wall clock time, including time zone
  26. !
  27. ! 'greg' : Gregorian calender, some years have a Februari 29
  28. ! '366' : every year has a Februari 29
  29. ! '365' : a year has never a Februari 29
  30. ! '360' : every month has 30 days
  31. !
  32. ! 'incr' : incremental time step: year=0, month=0, day >= 0
  33. !
  34. ! The 'incr' type is a special calender which has no year
  35. ! or month but might have any number of days.
  36. ! Note that day==1 has the interpretation of 24 hours for an 'incr',
  37. ! but means 'first' or 0 hours for one of the regular calenders.
  38. !
  39. ! Use the calender '360' if only operations on years and months are required.
  40. !
  41. !
  42. ! CREATING DATE STRUCTURES
  43. !
  44. ! To initialize a new date structure, a few routines are available.
  45. !
  46. ! Use routine 'NewDate' to initialize some fields and to fill
  47. ! the rest with zero's. If no calender is specified,
  48. ! the default value 'greg' is used (see also DEFAULTS).
  49. !
  50. ! t = NewDate( calender='greg', year=2000, month=1, ... )
  51. !
  52. ! Use routine 'IncrDate' to create a new increment;
  53. ! this is in fact a shorthand for a call to 'NewDate':
  54. !
  55. ! t = IncrDate( year=2000, month=1 )
  56. !
  57. ! Fill the time from the system clock in a date structure:
  58. !
  59. ! t = go_SystemDate()
  60. !
  61. !
  62. ! FIELD MANIPULATION
  63. !
  64. ! Use 'Set' to fill some specific fields of a date structure.
  65. ! Special arrays:
  66. ! time4 = (/year,month,day,hour/)
  67. ! time5 = (/year,month,day,hour,min/)
  68. ! time6 = (/year,month,day,hour,min,sec/)
  69. ! Example:
  70. !
  71. ! call Set( t [,year=2000] [,month=1] [,day=2] ... &
  72. ! [,time4=time4] [,time5=time5] [,time6=time6])
  73. !
  74. ! Use 'Get' to obtain some specific fields of a date structure.
  75. !
  76. ! call Get( t [,year=year] [,month=month] ... &
  77. ! [,time4=time4] [,time5=time5] [,time6=time6] )
  78. !
  79. ! Check contents of a date structure:
  80. !
  81. ! call Check( t )
  82. !
  83. ! Normalize hours to {0,..,23}, minutes to {0,..,59}, etc:
  84. !
  85. ! call Normalize( t )
  86. !
  87. !
  88. ! INQUIRY FUNCTIONS
  89. !
  90. ! A few inquiry functions are provided.
  91. !
  92. ! The logical function 'LeapYear' tells you if the year
  93. ! has a Februari 29 :
  94. !
  95. ! l = LeapYear( t )
  96. !
  97. ! Two integer functions are provided to count the total number
  98. ! of days in a month or a year:
  99. !
  100. ! i = Days_in_Month( t )
  101. ! i = Days_in_Year( t )
  102. !
  103. ! An integer function is provided to return the day number,
  104. ! counting from 1 (Januari 1) to 360, 365, or 366 (last of December):
  105. !
  106. ! i = DayNumber( t )
  107. !
  108. !
  109. ! OPERATORS
  110. !
  111. ! Operators '+' and '-' are redefined to perform operations
  112. ! between two date structures.
  113. ! Both should be of same calender type, or one should be
  114. ! an increment:
  115. !
  116. ! t = t1 + t2
  117. ! t = t1 - t2
  118. !
  119. ! Operators '*' and '/' are redefined for multiplication with
  120. ! or division by a real or an integer:
  121. !
  122. ! t = t1 + dt * 2
  123. ! t = t1 + dt * 3.1415
  124. ! t = t1 + dt / 3.1415
  125. !
  126. !
  127. ! LOGICAL OPERATORS
  128. !
  129. ! Operators '==', '/=', '<', '<=', '>', '>=' are defined to
  130. ! compare two dates.
  131. !
  132. !
  133. ! SUMMATION ROUTINES
  134. !
  135. ! The total number in a certain unit is returned by 'rTotal'
  136. ! (real value) or 'iTotal' (integer, error if not possible).
  137. ! Currently supported units are 'year', 'month', 'day',
  138. ! 'hour', 'min', 'sec', and 'mili'. If the total number is
  139. ! not wel defined for a certain date, for example the
  140. ! total number of years of today, an error message is produced.
  141. !
  142. ! r = rTotal( t, 'year'|'month'|... )
  143. ! i = iTotal( t, 'year'|'month'|... )
  144. !
  145. !
  146. ! INTERPOLATION
  147. !
  148. ! For t in [t1,t2], return real coefficients alfa1 and alf2 such that:
  149. ! t = alfa1 * t1 + alfa2 * t2
  150. ! Usefull for linear interpolation:
  151. ! f(t) ~ alfa1 * f(t1) + alfa2 * f(t2)
  152. !
  153. ! call InterpolFractions( t, t1, t2, alfa1, alfa2, status )
  154. !
  155. !
  156. ! OUTPUT
  157. !
  158. ! To obtain a pretty formatted print of the value of a date,
  159. ! the 'Pretty' routine is provided. Output differs based on
  160. ! the calender type.
  161. !
  162. ! print *, 't = '//trim(Pretty(t))
  163. !
  164. ! Some compilers have problems with this kind of statements.
  165. ! Therefore, also a routine is provided:
  166. !
  167. ! call PrintDate( 't = ', t )
  168. !
  169. !
  170. ! DEFAULTS
  171. !
  172. ! For setting some default values, the subroutine 'go_DateDefaults'
  173. ! is available. All arguments are optional:
  174. !
  175. ! call go_DateDefaults( [calender='greg'] )
  176. !
  177. !
  178. !###############################################################################
  179. !
  180. #define IF_NOTOK_RETURN(action) if (status/=0) then; write (gol,'("in ",a)') rname; call goErr; action; return; end if
  181. !
  182. ! print times up to minutes:
  183. #define PRINT_MINU
  184. !
  185. !###############################################################################
  186. module GO_Date
  187. use GO_Print, only : gol, goErr, goPr
  188. implicit none
  189. ! --- in/out ---------------------------
  190. private
  191. public :: TDate, TIncrDate
  192. public :: goDateDefaults
  193. public :: NewDate, IncrDate, AnyDate, SystemDate
  194. public :: Set, Get
  195. public :: Check
  196. public :: Normalize
  197. public :: LeapYear
  198. public :: days_in_month
  199. public :: days_in_year
  200. public :: DayNumber
  201. public :: operator(+)
  202. public :: operator(-)
  203. public :: operator(*)
  204. public :: operator(/)
  205. public :: Pretty
  206. public :: IsAnyDate
  207. public :: operator(==)
  208. public :: operator(/=)
  209. public :: operator(>)
  210. public :: operator(<)
  211. public :: operator(>=)
  212. public :: operator(<=)
  213. public :: rTotal, iTotal
  214. public :: InterpolFractions
  215. public :: wrtgol
  216. ! --- const -----------------------------------
  217. character(len=*), parameter :: mname = 'GO_Date'
  218. ! --- types -------------------------------------
  219. ! Strucure with fields to store year, month, day,
  220. ! hour and minute.
  221. ! Operators for assignment (=), adding (+),
  222. ! and comparission (==,<,>,>= and <=)
  223. ! have been defined for operations between
  224. ! instances of this type.
  225. type TDate
  226. ! type of calender: 'greg', '365', '360'
  227. character(len=4) :: calender
  228. ! year, month etc:
  229. integer :: year, month, day, hour, min, sec, mili
  230. ! difference with Coordinated Universal Time (UTC)
  231. integer :: zone ! minutes
  232. ! error status
  233. integer :: status = 1
  234. end type TDate
  235. type TIncrDate
  236. ! days, hours, etc:
  237. integer :: day, hour, min, sec, mili
  238. ! error status
  239. integer :: status = 1
  240. end type TIncrDate
  241. ! --- var --------------------------------
  242. ! default calender type
  243. character(len=4) :: default_calender = 'greg'
  244. ! --- interface ---------------------------
  245. interface Pretty
  246. module procedure date_Pretty
  247. module procedure incrdate_Pretty
  248. end interface
  249. interface Check
  250. module procedure date_Check
  251. module procedure incrdate_Check
  252. end interface
  253. ! *
  254. interface LeapYear
  255. module procedure date_LeapYear
  256. end interface
  257. interface days_in_month
  258. module procedure date_days_in_month
  259. end interface
  260. interface days_in_year
  261. module procedure date_days_in_year
  262. end interface
  263. interface DayNumber
  264. module procedure date_DayNumber
  265. end interface
  266. ! *
  267. interface Set
  268. module procedure date_Set
  269. module procedure incrdate_Set
  270. end interface
  271. interface Get
  272. module procedure date_Get
  273. module procedure incrdate_Get
  274. end interface
  275. ! *
  276. interface NewDate
  277. module procedure date_NewDate
  278. end interface
  279. interface AnyDate
  280. module procedure date_AnyDate
  281. end interface
  282. interface IncrDate
  283. module procedure incrdate_IncrDate
  284. end interface
  285. interface SystemDate
  286. module procedure date_SystemDate
  287. end interface
  288. ! * operators
  289. interface Normalize
  290. module procedure date_Normalize
  291. module procedure incrdate_Normalize
  292. end interface
  293. interface operator(+)
  294. module procedure t_plus_t
  295. module procedure t_plus_dt
  296. module procedure dt_plus_dt
  297. end interface
  298. interface operator(-)
  299. module procedure t_min_t
  300. module procedure t_min_dt
  301. module procedure dt_min_dt
  302. end interface
  303. interface operator(*)
  304. module procedure dt_times_r
  305. module procedure r_times_dt
  306. module procedure dt_times_i
  307. module procedure i_times_dt
  308. end interface
  309. interface operator(/)
  310. module procedure dt_div_r
  311. module procedure dt_div_i
  312. end interface
  313. ! * logical operators
  314. interface IsAnyDate
  315. module procedure date_IsAnyDate
  316. end interface
  317. interface operator(==)
  318. module procedure date_eq_date
  319. end interface
  320. interface operator(/=)
  321. module procedure date_ne_date
  322. end interface
  323. interface operator(>)
  324. module procedure date_gt_date
  325. end interface
  326. interface operator(<)
  327. module procedure date_lt_date
  328. end interface
  329. interface operator(>=)
  330. module procedure date_ge_date
  331. end interface
  332. interface operator(<=)
  333. module procedure date_le_date
  334. end interface
  335. ! *
  336. interface rTotal
  337. module procedure date_rTotal
  338. module procedure incr_rTotal
  339. end interface
  340. interface iTotal
  341. module procedure date_iTotal
  342. module procedure incrdate_iTotal
  343. end interface
  344. ! *
  345. interface InterpolFractions
  346. module procedure date_InterpolFractions
  347. end interface
  348. ! *
  349. interface wrtgol
  350. module procedure wrtgol_t
  351. module procedure wrtgol_dt
  352. module procedure wrtgol_t1_t2
  353. module procedure wrtgol_t1_t2_t3
  354. end interface
  355. contains
  356. ! ****************************************************
  357. ! ***
  358. ! *** set defaults
  359. ! ***
  360. ! ****************************************************
  361. subroutine goDateDefaults( calender )
  362. ! --- in/out --------------------------------
  363. character(len=*), intent(in), optional :: calender
  364. ! --- begin ----------------------------------
  365. if ( present(calender) ) default_calender = calender
  366. end subroutine goDateDefaults
  367. ! ****************************************************
  368. ! ***
  369. ! *** check
  370. ! ***
  371. ! ****************************************************
  372. !
  373. ! Check fields of a date:
  374. ! range etc
  375. !
  376. subroutine date_Check( t, status )
  377. use GO_Print, only : gol, goErr
  378. ! --- in/out ----------------------------------
  379. type(TDate), intent(in) :: t
  380. integer, intent(out) :: status
  381. ! --- const -----------------------------------
  382. character(len=*), parameter :: rname = mname//'/date_Check'
  383. ! --- begin -----------------------------------
  384. ! already error status ? then leave immediatelly:
  385. if ( t%status /= 0 ) then
  386. write (gol,'("found error status in date")'); call goErr
  387. write (gol,'(" year,month,day : ",3i6)') t%year, t%month, t%day; call goErr
  388. write (gol,'(" hour,minu,sec,mili : ",4i6)') t%hour, t%min, t%sec, t%mili; call goErr
  389. write (gol,'("in ",a)') rname; call goErr; status=1; return
  390. end if
  391. ! calender specific
  392. select case ( t%calender )
  393. case ( 'any' )
  394. ! always ok ...
  395. status = 0
  396. return
  397. case ( 'wall' )
  398. ! no special tests
  399. case ( 'greg', '366', '365', '360' )
  400. ! check month
  401. if ( t%month<1 .or. t%month>12 ) then
  402. call wrtgol( 'strange month in ', t ); call goErr
  403. write (gol,'("in ",a)') rname; call goErr; status=1; return
  404. end if
  405. ! check day
  406. if ( t%day<1 .or. t%day>days_in_month(t) ) then
  407. call wrtgol( 'strange day in ', t ); call goErr
  408. write (gol,'("in ",a)') rname; call goErr; status=1; return
  409. end if
  410. ! zone should be zero:
  411. if ( t%zone /= 0 ) then
  412. call wrtgol( 'expecting zero zone in date ', t ); call goErr
  413. write (gol,'("in ",a)') rname; call goErr; status=1; return
  414. end if
  415. case default
  416. write (gol,'("unknown calender type: `",a,"`")') t%calender; call goErr
  417. write (gol,'(" year etc : ",6i5)') t%year, t%month, t%day, t%hour, t%min, t%sec; call goErr
  418. write (gol,'("in ",a)') rname; call goErr; status=1; return
  419. end select
  420. ! check minutes
  421. if ( t%min<0 .or. t%min>59 ) then
  422. call wrtgol( 'found strange minutes in ', t ); call goErr
  423. write (gol,'("in ",a)') rname; call goErr; status=1; return
  424. end if
  425. ! check seconds
  426. if ( t%sec<0 .or. t%sec>59 ) then
  427. call wrtgol( 'found strange seconds in ', t ); call goErr
  428. write (gol,'("in ",a)') rname; call goErr; status=1; return
  429. end if
  430. ! check mili
  431. if ( t%mili<0 .or. t%mili>999 ) then
  432. call wrtgol( 'found strange mili seconds in ', t ); call goErr
  433. write (gol,'("in ",a)') rname; call goErr; status=1; return
  434. end if
  435. ! ok
  436. status = 0
  437. end subroutine date_Check
  438. ! ***
  439. subroutine incrdate_Check( dt, status )
  440. use GO_Print, only : gol, goErr
  441. ! --- in/out ----------------------------------
  442. type(TIncrDate), intent(in) :: dt
  443. integer, intent(out) :: status
  444. ! --- const -----------------------------------
  445. character(len=*), parameter :: rname = mname//'/incrdate_Check'
  446. ! --- begin -----------------------------------
  447. ! already error status ? then leave immediatelly:
  448. if ( dt%status /= 0 ) then
  449. write (gol,'("found error status in incrdate")'); call goErr
  450. write (gol,'(" day, hour,minu,sec,mili : ",5i6)') dt%day, dt%hour, dt%min, dt%sec, dt%mili; call goErr
  451. write (gol,'("in ",a)') rname; call goErr; status=1; return
  452. end if
  453. ! every value is allowed for increments ...
  454. ! ok
  455. status = 0
  456. end subroutine incrdate_Check
  457. ! ****************************************************
  458. ! ***
  459. ! *** computation
  460. ! ***
  461. ! ****************************************************
  462. ! Does this year have a 29 feb ?
  463. logical function calc_LeapYear( year )
  464. ! --- in/out -------------------------------
  465. integer, intent(in) :: year
  466. ! --- begin --------------------------------
  467. calc_LeapYear = ( (mod(year,4)==0) .and. .not.(mod(year,100)==0) ) &
  468. .or. (mod(year,400)==0)
  469. end function calc_LeapYear
  470. ! ***
  471. ! days per month
  472. integer function calc_days_in_month( calender, year, month )
  473. use GO_Print, only : gol, goErr
  474. ! --- in/out ---------------------------
  475. character(len=*), intent(in) :: calender
  476. integer, intent(in) :: year, month
  477. ! --- const -----------------------------
  478. character(len=*), parameter :: rname = mname//'/calc_days_in_month'
  479. ! --- const -----------------------------
  480. ! days in a month 1 2 3 4 5 6 7 8 9 10 11 12
  481. integer, parameter :: days365(12) = (/31,28,31,30,31,30,31,31,30,31,30,31/) ! normal
  482. integer, parameter :: days366(12) = (/31,29,31,30,31,30,31,31,30,31,30,31/) ! leap year
  483. integer, parameter :: days360(12) = (/30,30,30,30,30,30,30,30,30,30,30,30/) ! fixed month
  484. ! --- begin ----------------
  485. select case ( calender )
  486. case ( 'wall', 'greg' )
  487. if ( calc_LeapYear(year) ) then
  488. calc_days_in_month = days366(month)
  489. else
  490. calc_days_in_month = days365(month)
  491. end if
  492. case ( '366' )
  493. calc_days_in_month = days366(month)
  494. case ( '365' )
  495. calc_days_in_month = days365(month)
  496. case ( '360' )
  497. calc_days_in_month = days360(month)
  498. case ( 'any' )
  499. calc_days_in_month = 0
  500. case default
  501. calc_days_in_month = -1
  502. write (gol,'("unknown calender type: ",a)') calender; call goErr
  503. write (gol,'("in ",a)') rname; call goErr; calc_days_in_month=-1; return
  504. end select
  505. end function calc_days_in_month
  506. ! ***
  507. ! days per month
  508. integer function calc_days_in_year( calender, year )
  509. use GO_Print, only : gol, goErr
  510. ! --- in/out ----------------
  511. character(len=*), intent(in) :: calender
  512. integer, intent(in) :: year
  513. ! --- const -----------------------------
  514. character(len=*), parameter :: rname = mname//'/calc_days_in_year'
  515. ! --- begin ----------------
  516. select case ( calender )
  517. case ( 'wall', 'greg' )
  518. if ( calc_LeapYear(year) ) then
  519. calc_days_in_year = 366
  520. else
  521. calc_days_in_year = 365
  522. end if
  523. case ( '366' )
  524. calc_days_in_year = 366
  525. case ( '365' )
  526. calc_days_in_year = 365
  527. case ( '360' )
  528. calc_days_in_year = 360
  529. case ( 'any' )
  530. calc_days_in_year = 0
  531. case default
  532. write (gol,'("unknown calender type: ",a)') calender; call goErr
  533. write (gol,'("in ",a)') rname; call goErr; calc_days_in_year=-1; return
  534. end select
  535. end function calc_days_in_year
  536. ! ***
  537. ! Returns the number of the day spedified by the date iy/im/id.
  538. ! The existence of a february 29 is checked.
  539. !
  540. ! ndays( 1995, 1, 1 ) = 1
  541. ! ndays( 1995, 12, 31 ) = 365
  542. ! ndays( 1996, 12, 31 ) = 366 29 feb every 4 year ...
  543. ! ndays( 1900, 12, 31 ) = 365 except every 100 year ...
  544. ! ndays( 2000, 12, 31 ) = 366 except every 400 year ...
  545. integer function calc_DayNumber( calender, year, month, day )
  546. use GO_Print, only : gol, goErr
  547. ! --- in/out ----------------------------
  548. character(len=*), intent(in) :: calender
  549. integer, intent(in) :: year, month, day
  550. ! --- const -----------------------------
  551. character(len=*), parameter :: rname = mname//'/calc_DayNumber'
  552. ! --- local -----------------------------
  553. integer :: imonth
  554. ! --- begin ----------------------------
  555. select case ( calender )
  556. case ( 'wall', 'greg', '366', '365', '360' )
  557. calc_DayNumber = day
  558. do imonth = 1, month-1
  559. calc_DayNumber = calc_DayNumber + calc_days_in_month(calender,year,imonth)
  560. end do
  561. case ( 'any' )
  562. calc_DayNumber = 0
  563. case default
  564. write (gol,'("unknown calender type: ",a)') calender; call goErr
  565. write (gol,'("in ",a)') rname; call goErr; calc_DayNumber=-1; return
  566. end select
  567. end function calc_DayNumber
  568. ! **********************************************
  569. logical function date_LeapYear( t )
  570. ! --- in/out -------------------------------
  571. type(TDate), intent(in) :: t
  572. ! --- begin --------------------------------
  573. ! calender specific
  574. select case ( t%calender )
  575. case ( 'wall', 'greg' )
  576. ! see above ...
  577. date_LeapYear = calc_LeapYear( t%year )
  578. case default
  579. ! no leap years ...
  580. date_LeapYear = .false.
  581. end select
  582. end function date_LeapYear
  583. ! ***
  584. integer function date_days_in_month( t )
  585. ! --- in/out ----------------
  586. type(TDate), intent(in) :: t
  587. ! --- begin ----------------
  588. date_days_in_month = calc_days_in_month( t%calender, t%year, t%month )
  589. end function date_days_in_month
  590. ! ***
  591. integer function date_days_in_year( t )
  592. ! --- in/out ----------------
  593. type(TDate), intent(in) :: t
  594. ! --- begin ----------------
  595. date_days_in_year = calc_days_in_year( t%calender, t%year )
  596. end function date_days_in_year
  597. ! ***
  598. integer function date_DayNumber( t )
  599. ! --- in/out ----------------
  600. type(TDate), intent(in) :: t
  601. ! --- begin ----------------
  602. date_DayNumber = calc_DayNumber( t%calender, t%year, t%month, t%day )
  603. end function date_DayNumber
  604. ! ****************************************************
  605. ! ***
  606. ! *** Set/Get fields in a structure TDate
  607. ! ***
  608. ! ****************************************************
  609. !
  610. ! Fill fields in a 'TDate' structure.
  611. !
  612. subroutine date_Set( date, year, month, day, hour, min, sec, mili, &
  613. zone, calender, time4, time5, time6 )
  614. ! --- in/out ------------------------------------
  615. type(TDate), intent(inout) :: date
  616. integer, intent(in), optional :: year
  617. integer, intent(in), optional :: month
  618. integer, intent(in), optional :: day
  619. integer, intent(in), optional :: hour
  620. integer, intent(in), optional :: min
  621. integer, intent(in), optional :: sec
  622. integer, intent(in), optional :: mili
  623. integer, intent(in), optional :: zone
  624. character(len=*), intent(in), optional :: calender
  625. integer, intent(in), optional :: time4(4)
  626. integer, intent(in), optional :: time5(5)
  627. integer, intent(in), optional :: time6(6)
  628. ! --- local ----------------------------------
  629. if ( present(calender) ) date%calender = calender
  630. if ( present(time4) ) then
  631. date%year = time4(1)
  632. date%month = time4(2)
  633. date%day = time4(3)
  634. date%hour = time4(4)
  635. end if
  636. if ( present(time5) ) then
  637. date%year = time5(1)
  638. date%month = time5(2)
  639. date%day = time5(3)
  640. date%hour = time5(4)
  641. date%min = time5(5)
  642. end if
  643. if ( present(time6) ) then
  644. date%year = time6(1)
  645. date%month = time6(2)
  646. date%day = time6(3)
  647. date%hour = time6(4)
  648. date%min = time6(5)
  649. date%sec = time6(6)
  650. end if
  651. if ( present(year ) ) date%year = year
  652. if ( present(month) ) date%month = month
  653. if ( present(day ) ) date%day = day
  654. if ( present(zone ) ) date%zone = zone
  655. if ( present(hour ) ) date%hour = hour
  656. if ( present(min ) ) date%min = min
  657. if ( present(sec ) ) date%sec = sec
  658. if ( present(mili ) ) date%mili = mili
  659. end subroutine date_Set
  660. ! *
  661. subroutine incrdate_Set( date, day, hour, min, sec, mili )
  662. ! --- in/out ------------------------------------
  663. type(TIncrDate), intent(inout) :: date
  664. integer, intent(in), optional :: day
  665. integer, intent(in), optional :: hour
  666. integer, intent(in), optional :: min
  667. integer, intent(in), optional :: sec
  668. integer, intent(in), optional :: mili
  669. ! --- local ----------------------------------
  670. if ( present(day ) ) date%day = day
  671. if ( present(hour ) ) date%hour = hour
  672. if ( present(min ) ) date%min = min
  673. if ( present(sec ) ) date%sec = sec
  674. if ( present(mili ) ) date%mili = mili
  675. end subroutine incrdate_Set
  676. !
  677. ! Obtain fields from a 'TDate' structure.
  678. !
  679. subroutine date_Get( date, &
  680. year, month, day, hour, min, sec, mili, &
  681. zone, calender, time4, time5, time6 )
  682. ! --- in/out ------------------------------------
  683. type(TDate), intent(in) :: date
  684. integer, intent(out), optional :: year, month, day
  685. integer, intent(out), optional :: hour, min, sec, mili
  686. integer, intent(out), optional :: zone
  687. integer, intent(out), optional :: time4(4)
  688. integer, intent(out), optional :: time5(5)
  689. integer, intent(out), optional :: time6(6)
  690. character(len=*), intent(out), optional :: calender
  691. ! --- local ----------------------------------
  692. if ( present(calender) ) calender = date%calender
  693. if ( present(year) ) year = date%year
  694. if ( present(month) ) month = date%month
  695. if ( present(day ) ) day = date%day
  696. if ( present(zone ) ) zone = date%zone
  697. if ( present(hour ) ) hour = date%hour
  698. if ( present(min ) ) min = date%min
  699. if ( present(sec ) ) sec = date%sec
  700. if ( present(mili ) ) mili = date%mili
  701. if ( present(time4) ) time4 = (/ date%year, date%month, date%day, date%hour /)
  702. if ( present(time5) ) time5 = (/ date%year, date%month, date%day, &
  703. date%hour, date%min /)
  704. if ( present(time6) ) time6 = (/ date%year, date%month, date%day, &
  705. date%hour, date%min , date%sec /)
  706. end subroutine date_Get
  707. ! *
  708. subroutine incrdate_Get( date, day, hour, min, sec, mili )
  709. ! --- in/out ------------------------------------
  710. type(TIncrDate), intent(in) :: date
  711. integer, intent(out), optional :: day
  712. integer, intent(out), optional :: hour, min, sec, mili
  713. ! --- local ----------------------------------
  714. if ( present(day ) ) day = date%day
  715. if ( present(hour ) ) hour = date%hour
  716. if ( present(min ) ) min = date%min
  717. if ( present(sec ) ) sec = date%sec
  718. if ( present(mili ) ) mili = date%mili
  719. end subroutine incrdate_Get
  720. ! ****************************************************
  721. ! ***
  722. ! *** Return a date structure
  723. ! ***
  724. ! ****************************************************
  725. !
  726. ! Set fields to zero or fill some of them.
  727. !
  728. type(TDate) function date_NewDate( year, month, day, hour, min, sec, mili, &
  729. zone, calender, time4, time5, time6 )
  730. ! --- in/out ------------------------------------
  731. integer, intent(in), optional :: year, month, day
  732. integer, intent(in), optional :: hour, min, sec, mili
  733. integer, intent(in), optional :: zone
  734. character(len=*), intent(in), optional :: calender
  735. integer, intent(in), optional :: time4(4)
  736. integer, intent(in), optional :: time5(5)
  737. integer, intent(in), optional :: time6(6)
  738. ! --- local ----------------------------------
  739. ! set default calender type:
  740. date_NewDate%calender = default_calender
  741. ! Fields are zero by default:
  742. date_NewDate%year = 0
  743. date_NewDate%month = 0
  744. date_NewDate%day = 0
  745. date_NewDate%zone = 0
  746. date_NewDate%hour = 0
  747. date_NewDate%min = 0
  748. date_NewDate%sec = 0
  749. date_NewDate%mili = 0
  750. ! Optionally, change some of them:
  751. if ( present(year ) ) call Set( date_NewDate, year=year )
  752. if ( present(month ) ) call Set( date_NewDate, month=month )
  753. if ( present(day ) ) call Set( date_NewDate, day=day )
  754. if ( present(hour ) ) call Set( date_NewDate, hour=hour )
  755. if ( present(min ) ) call Set( date_NewDate, min=min )
  756. if ( present(sec ) ) call Set( date_NewDate, sec=sec )
  757. if ( present(mili ) ) call Set( date_NewDate, mili=mili )
  758. if ( present(zone ) ) call Set( date_NewDate, zone=zone )
  759. if ( present(calender) ) call Set( date_NewDate, calender=calender )
  760. if ( present(time4 ) ) call Set( date_NewDate, time4=time4 )
  761. if ( present(time5 ) ) call Set( date_NewDate, time5=time5 )
  762. if ( present(time6 ) ) call Set( date_NewDate, time6=time6 )
  763. ! normalize too small/too large values:
  764. if ( date_NewDate%year /= 0000 ) call Normalize( date_NewDate )
  765. ! data filled, thus probably no error ...
  766. date_NewDate%status = 0
  767. end function date_NewDate
  768. ! ***
  769. type(TIncrDate) function incrdate_IncrDate( day, hour, min, sec, mili )
  770. ! --- in/out ------------------------------------
  771. integer, intent(in), optional :: day
  772. integer, intent(in), optional :: hour, min, sec, mili
  773. ! --- local ----------------------------------
  774. ! Fields are zero by default:
  775. incrdate_IncrDate%day = 0
  776. incrdate_IncrDate%hour = 0
  777. incrdate_IncrDate%min = 0
  778. incrdate_IncrDate%sec = 0
  779. incrdate_IncrDate%mili = 0
  780. ! Optionally, change some of them:
  781. if ( present(day ) ) call Set( incrdate_IncrDate, day=day )
  782. if ( present(hour ) ) call Set( incrdate_IncrDate, hour=hour )
  783. if ( present(min ) ) call Set( incrdate_IncrDate, min=min )
  784. if ( present(sec ) ) call Set( incrdate_IncrDate, sec=sec )
  785. if ( present(mili ) ) call Set( incrdate_IncrDate, mili=mili )
  786. ! normalize too small/too large values:
  787. call Normalize( incrdate_IncrDate )
  788. ! data filled, thus probably no error ...
  789. incrdate_IncrDate%status = 0
  790. end function incrdate_IncrDate
  791. ! ***
  792. !
  793. ! Set fields to zero, special calender
  794. !
  795. type(TDate) function date_AnyDate()
  796. ! --- local ----------------------------------
  797. ! Set some fields, other are automatically zero:
  798. date_AnyDate = NewDate( calender='any' )
  799. end function date_AnyDate
  800. ! ***
  801. ! Fill with system time
  802. type(TDate) function date_SystemDate()
  803. ! --- in/out ------------------------------
  804. ! none ...
  805. ! --- local ------------------------------
  806. integer :: values(8)
  807. ! --- begin ------------------------------
  808. !
  809. ! Optional character output of Date_and_Time:
  810. !
  811. ! date '20020812'
  812. ! time '211757.314'
  813. ! zone '+0200'
  814. !
  815. ! obtain system date and time:
  816. call Date_and_Time( values=values )
  817. ! fill fields in structure:
  818. call Set( date_SystemDate, calender='wall', &
  819. year=values(1), month=values(2), day=values(3), &
  820. zone=values(4), hour=values(5), &
  821. min=values(6), sec=values(7), mili=values(8) )
  822. ! Date probably ok.
  823. date_SystemDate%status = 0
  824. end function date_SystemDate
  825. ! ************************************************
  826. ! ***
  827. ! *** operators
  828. ! ***
  829. ! ************************************************
  830. subroutine date_Normalize( t )
  831. use go_print, only : gol, goErr
  832. ! --- in/out --------------------------------
  833. type(TDate), intent(inout) :: t
  834. ! --- const -----------------------------
  835. character(len=*), parameter :: rname = mname//'/date_Normalize'
  836. ! --- begin ---------------------------------
  837. ! mili seconds
  838. do
  839. if ( t%mili >= 0 ) exit
  840. t%sec = t%sec - 1
  841. t%mili = t%mili + 1000
  842. end do
  843. do
  844. if ( t%mili <= 999 ) exit
  845. t%mili = t%mili - 1000
  846. t%sec = t%sec + 1
  847. end do
  848. ! seconds
  849. do
  850. if ( t%sec >= 0 ) exit
  851. t%min = t%min - 1
  852. t%sec = t%sec + 60
  853. end do
  854. do
  855. if ( t%sec <= 59 ) exit
  856. t%sec = t%sec - 60
  857. t%min = t%min + 1
  858. end do
  859. ! minutes
  860. do
  861. if ( t%min >= 0 ) exit
  862. t%hour = t%hour - 1
  863. t%min = t%min + 60
  864. end do
  865. do
  866. if ( t%min <= 59 ) exit
  867. t%min = t%min - 60
  868. t%hour = t%hour + 1
  869. end do
  870. ! hours
  871. do
  872. if ( t%hour >= 0 ) exit
  873. t%day = t%day - 1
  874. t%hour = t%hour + 24
  875. end do
  876. do
  877. if ( t%hour <= 23 ) exit
  878. t%hour = t%hour - 24
  879. t%day = t%day + 1
  880. end do
  881. ! days, months, year
  882. select case ( t%calender )
  883. case ( 'wall', 'greg', '366', '365', '360' )
  884. do
  885. if ( t%day >= 1 ) exit
  886. t%month = t%month - 1
  887. do
  888. if ( t%month >= 1 ) exit
  889. t%year = t%year - 1
  890. t%month = t%month + 12
  891. end do
  892. t%day = t%day + days_in_month(t)
  893. end do
  894. do
  895. if ( t%day <= days_in_month(t) ) exit
  896. t%day = t%day - days_in_month(t)
  897. t%month = t%month + 1
  898. do
  899. if ( t%month <= 12 ) exit
  900. t%month = t%month - 12
  901. t%year = t%year + 1
  902. end do
  903. end do
  904. case default
  905. write (gol,'("unsupported calender type: ",a)') t%calender; call goErr
  906. write (gol,'("in ",a)') rname; call goErr; t%status=1; return
  907. end select
  908. end subroutine date_Normalize
  909. subroutine incrdate_Normalize( dt )
  910. use go_print, only : gol, goErr
  911. ! --- in/out --------------------------------
  912. type(TIncrDate), intent(inout) :: dt
  913. ! --- const -----------------------------
  914. character(len=*), parameter :: rname = mname//'/incrdate_Normalize'
  915. ! --- begin ---------------------------------
  916. ! mili seconds
  917. do
  918. if ( dt%mili >= 0 ) exit
  919. dt%sec = dt%sec - 1
  920. dt%mili = dt%mili + 1000
  921. end do
  922. do
  923. if ( dt%mili <= 999 ) exit
  924. dt%mili = dt%mili - 1000
  925. dt%sec = dt%sec + 1
  926. end do
  927. ! seconds
  928. do
  929. if ( dt%sec >= 0 ) exit
  930. dt%min = dt%min - 1
  931. dt%sec = dt%sec + 60
  932. end do
  933. do
  934. if ( dt%sec <= 59 ) exit
  935. dt%sec = dt%sec - 60
  936. dt%min = dt%min + 1
  937. end do
  938. ! minutes
  939. do
  940. if ( dt%min >= 0 ) exit
  941. dt%hour = dt%hour - 1
  942. dt%min = dt%min + 60
  943. end do
  944. do
  945. if ( dt%min <= 59 ) exit
  946. dt%min = dt%min - 60
  947. dt%hour = dt%hour + 1
  948. end do
  949. ! hours
  950. do
  951. if ( dt%hour >= 0 ) exit
  952. dt%day = dt%day - 1
  953. dt%hour = dt%hour + 24
  954. end do
  955. do
  956. if ( dt%hour <= 23 ) exit
  957. dt%hour = dt%hour - 24
  958. dt%day = dt%day + 1
  959. end do
  960. end subroutine incrdate_Normalize
  961. ! *** date = t1 + t2 ************************
  962. !
  963. ! t1 + t2 -> t1+t2
  964. !
  965. ! greg incr greg
  966. ! 366 incr 366
  967. ! 365 incr 365
  968. !
  969. ! 360 360 360
  970. ! 360 incr 360
  971. !
  972. ! incr greg greg
  973. ! incr 366 366
  974. ! incr 365 365
  975. ! incr 360 360
  976. ! incr incr incr
  977. !
  978. type(TDate) function t_plus_t( t1, t2 )
  979. use go_print, only : gol, goErr
  980. ! --- in/out --------------------------------
  981. type(TDate), intent(in) :: t1
  982. type(TDate), intent(in) :: t2
  983. ! --- const -----------------------------------
  984. character(len=*), parameter :: rname = mname//'/t_plus_t'
  985. ! --- local --------------------------------
  986. integer :: status
  987. ! --- begin ---------------------------------
  988. ! check arguments
  989. call Check( t1, status )
  990. IF_NOTOK_RETURN(t_plus_t%status=1)
  991. call Check( t2, status )
  992. IF_NOTOK_RETURN(t_plus_t%status=1)
  993. ! any date ? return any date ..
  994. if ( (t1%calender == 'any') .or. (t2%calender == 'any') ) then
  995. t_plus_t = AnyDate()
  996. return
  997. end if
  998. ! calenders should be the same:
  999. if ( t1%calender /= t2%calender ) then
  1000. write (gol,'("calenders should be the same : ")'); call goPr
  1001. write (gol,'(" t1 : ",a)') trim(t1%calender); call goPr
  1002. write (gol,'(" t2 : ",a)') trim(t2%calender); call goPr
  1003. write (gol,'("in ",a)') rname; call goErr; t_plus_t%status=1; return
  1004. end if
  1005. ! add all fields;
  1006. t_plus_t = NewDate( calender=t1%calender, &
  1007. year = t1%year + t2%year , &
  1008. month = t1%month + t2%month , &
  1009. day = t1%day + t2%day , &
  1010. hour = t1%hour + t2%hour , &
  1011. zone = t1%zone + t2%zone , &
  1012. min = t1%min + t2%min , &
  1013. sec = t1%sec + t2%sec , &
  1014. mili = t1%mili + t2%mili )
  1015. end function t_plus_t
  1016. ! *
  1017. type(TDate) function t_plus_dt( t, dt )
  1018. use go_print, only : gol, goErr
  1019. ! --- in/out --------------------------------
  1020. type(TDate), intent(in) :: t
  1021. type(TIncrDate), intent(in) :: dt
  1022. ! --- const -----------------------------------
  1023. character(len=*), parameter :: rname = mname//'/t_plus_dt'
  1024. ! --- local --------------------------------
  1025. integer :: status
  1026. ! --- begin ---------------------------------
  1027. ! check arguments
  1028. call Check( t, status )
  1029. IF_NOTOK_RETURN(t_plus_dt%status=1)
  1030. call Check( dt, status )
  1031. IF_NOTOK_RETURN(t_plus_dt%status=1)
  1032. ! any date ? return any date ..
  1033. if ( t%calender == 'any' ) then
  1034. t_plus_dt = AnyDate()
  1035. return
  1036. end if
  1037. ! add fields; normalization is applied in routine:
  1038. t_plus_dt = NewDate( calender = t%calender, &
  1039. year = t%year , &
  1040. month = t%month , &
  1041. day = t%day + dt%day , &
  1042. hour = t%hour + dt%hour , &
  1043. zone = t%zone , &
  1044. min = t%min + dt%min , &
  1045. sec = t%sec + dt%sec , &
  1046. mili = t%mili + dt%mili )
  1047. end function t_plus_dt
  1048. ! *
  1049. type(TIncrDate) function dt_plus_dt( dt1, dt2 )
  1050. use go_print, only : gol, goErr
  1051. ! --- in/out --------------------------------
  1052. type(TIncrDate), intent(in) :: dt1
  1053. type(TIncrDate), intent(in) :: dt2
  1054. ! --- const -----------------------------------
  1055. character(len=*), parameter :: rname = mname//'/dt_plus_dt'
  1056. ! --- local --------------------------------
  1057. integer :: status
  1058. ! --- begin ---------------------------------
  1059. ! check arguments
  1060. call Check( dt1, status )
  1061. IF_NOTOK_RETURN(dt_plus_dt%status=1)
  1062. call Check( dt2, status )
  1063. IF_NOTOK_RETURN(dt_plus_dt%status=1)
  1064. ! add fields:
  1065. dt_plus_dt = IncrDate( day = dt1%day + dt2%day , &
  1066. hour = dt1%hour + dt2%hour , &
  1067. min = dt1%min + dt2%min , &
  1068. sec = dt1%sec + dt2%sec , &
  1069. mili = dt1%mili + dt2%mili )
  1070. end function dt_plus_dt
  1071. ! *** date = t1 - t2
  1072. !
  1073. ! t1 -> t2 -> t1-t2 action
  1074. !
  1075. ! greg greg incr difference
  1076. ! greg incr greg minus
  1077. !
  1078. ! 366 366 incr difference
  1079. ! 366 incr 366 minus
  1080. !
  1081. ! 365 365 incr difference
  1082. ! 365 incr 365 minus
  1083. !
  1084. ! 360 360 360 difference
  1085. ! 360 incr 360 minus
  1086. !
  1087. ! incr incr incr difference
  1088. !
  1089. type(TIncrDate) function t_min_t( t1, t2 )
  1090. use go_print, only : gol, goErr
  1091. ! --- in/out --------------------------------
  1092. type(TDate), intent(in) :: t1
  1093. type(TDate), intent(in) :: t2
  1094. ! --- const -----------------------------------
  1095. character(len=*), parameter :: rname = mname//'/t_min_t'
  1096. ! --- local ---------------------------------
  1097. integer :: status
  1098. character(len=5) :: action
  1099. integer :: ndays
  1100. type(TDate) :: t
  1101. ! --- begin ---------------------------------
  1102. ! check arguments
  1103. call Check( t1, status )
  1104. IF_NOTOK_RETURN(t_min_t%status=1)
  1105. call Check( t2, status )
  1106. IF_NOTOK_RETURN(t_min_t%status=1)
  1107. ! any dates ? something wrong ...
  1108. if ( (t1%calender == 'any') .or. (t2%calender == 'any') ) then
  1109. write (gol,'("do not know how to compute difference between `any` dates ...")')
  1110. write (gol,'("in ",a)') rname; call goErr; t_min_t%status=1; return
  1111. end if
  1112. ! calenders should be the same:
  1113. if ( t1%calender /= t2%calender ) then
  1114. write (gol,'("calenders should be the same : ")'); call goPr
  1115. write (gol,'(" t1 : ",a)') trim(t1%calender); call goPr
  1116. write (gol,'(" t2 : ",a)') trim(t2%calender); call goPr
  1117. write (gol,'("in ",a)') rname; call goErr; t_min_t%status=1; return
  1118. end if
  1119. ! difference between two dates; result is an increment
  1120. ! difference should be positive:
  1121. if ( t1 < t2 ) then
  1122. write (gol,'("expect t1 to exceed t2 :")'); call goErr
  1123. call wrtgol( ' t1 : ', t1 ); call goErr
  1124. call wrtgol( ' t2 : ', t2 ); call goErr
  1125. write (gol,'("in ",a)') rname; call goErr; t_min_t%status=1; return
  1126. end if
  1127. ! determine number of days between t1 and t2:
  1128. t = t1
  1129. ndays = daynumber(t) - 1
  1130. do
  1131. if ( t%year==t2%year ) exit
  1132. t%year = t%year - 1
  1133. ndays = ndays + days_in_year(t)
  1134. end do
  1135. ndays = ndays - (daynumber(t2)-1)
  1136. ! store result:
  1137. t_min_t = IncrDate( day = ndays, &
  1138. hour = t1%hour - t2%hour, &
  1139. min = t1%min - t2%min , &
  1140. sec = t1%sec - t2%sec , &
  1141. mili = t1%mili - t2%mili )
  1142. end function t_min_t
  1143. ! *
  1144. type(TDate) function t_min_dt( t, dt )
  1145. use go_print, only : gol, goErr
  1146. ! --- in/out --------------------------------
  1147. type(TDate), intent(in) :: t
  1148. type(TIncrDate), intent(in) :: dt
  1149. ! --- const -----------------------------------
  1150. character(len=*), parameter :: rname = mname//'/t_min_dt'
  1151. ! --- local ---------------------------------
  1152. integer :: status
  1153. ! --- begin ---------------------------------
  1154. ! check arguments
  1155. call Check( t, status )
  1156. IF_NOTOK_RETURN(t_min_dt%status=1)
  1157. call Check( dt, status )
  1158. IF_NOTOK_RETURN(t_min_dt%status=1)
  1159. ! any date ? return any date ..
  1160. if ( t%calender == 'any' ) then
  1161. t_min_dt = AnyDate()
  1162. return
  1163. end if
  1164. ! result is of same type as t;
  1165. ! normalization is done in NewDate
  1166. t_min_dt = NewDate( calender = t%calender , &
  1167. year = t%year , &
  1168. month = t%month , &
  1169. day = t%day -dt%day , &
  1170. hour = t%hour -dt%hour , &
  1171. zone = t%zone , &
  1172. min = t%min -dt%min , &
  1173. sec = t%sec -dt%sec , &
  1174. mili = t%mili -dt%mili )
  1175. end function t_min_dt
  1176. ! *
  1177. type(TIncrDate) function dt_min_dt( dt1, dt2 )
  1178. use go_print, only : gol, goErr
  1179. ! --- in/out --------------------------------
  1180. type(TIncrDate), intent(in) :: dt1
  1181. type(TIncrDate), intent(in) :: dt2
  1182. ! --- const -----------------------------------
  1183. character(len=*), parameter :: rname = mname//'/dt_min_dt'
  1184. ! --- local ---------------------------------
  1185. integer :: status
  1186. ! --- begin ---------------------------------
  1187. ! check arguments
  1188. call Check( dt1, status )
  1189. IF_NOTOK_RETURN(dt_min_dt%status=1)
  1190. call Check( dt2, status )
  1191. IF_NOTOK_RETURN(dt_min_dt%status=1)
  1192. ! fill result:
  1193. dt_min_dt = IncrDate( day = dt1%day - dt2%day , &
  1194. hour = dt1%hour - dt2%hour, &
  1195. min = dt1%min - dt2%min , &
  1196. sec = dt1%sec - dt2%sec , &
  1197. mili = dt1%mili - dt2%mili )
  1198. end function dt_min_dt
  1199. ! *** date = t * r ************************************************
  1200. ! multiply time with a real factor;
  1201. ! use round for fractions
  1202. type(TIncrDate) function dt_times_r( dt, r )
  1203. use go_print, only : gol, goErr
  1204. ! --- in/out --------------------------------
  1205. type(TIncrDate), intent(in) :: dt
  1206. real, intent(in) :: r
  1207. ! --- const -----------------------------------
  1208. character(len=*), parameter :: rname = mname//'/dt_times_r'
  1209. ! --- local -----------------------------------
  1210. integer :: status
  1211. ! --- begin ---------------------------------
  1212. call Check( dt, status )
  1213. IF_NOTOK_RETURN(dt_times_r%status=1)
  1214. ! multiply each of the parts with r, round
  1215. dt_times_r = IncrDate( day = nint( dt%day * r ), &
  1216. hour = nint( dt%hour * r ), &
  1217. min = nint( dt%min * r ), &
  1218. sec = nint( dt%sec * r ), &
  1219. mili = nint( dt%mili * r ) )
  1220. end function dt_times_r
  1221. ! *
  1222. type(TIncrDate) function r_times_dt( r, dt )
  1223. ! --- in/out --------------------------------
  1224. real, intent(in) :: r
  1225. type(TIncrDate), intent(in) :: dt
  1226. ! --- begin ---------------------------------
  1227. r_times_dt = dt * r
  1228. end function r_times_dt
  1229. ! *
  1230. type(TIncrDate) function dt_times_i( dt, i )
  1231. ! --- in/out --------------------------------
  1232. type(TIncrDate), intent(in) :: dt
  1233. integer, intent(in) :: i
  1234. ! --- begin ---------------------------------
  1235. dt_times_i = dt * (i*1.0)
  1236. end function dt_times_i
  1237. ! *
  1238. type(TIncrDate) function i_times_dt( i, dt )
  1239. ! --- in/out --------------------------------
  1240. integer, intent(in) :: i
  1241. type(TIncrDate), intent(in) :: dt
  1242. ! --- begin ---------------------------------
  1243. i_times_dt = dt * i
  1244. end function i_times_dt
  1245. ! *** dt = dt / r ************************************************
  1246. type(TIncrDate) function dt_div_r( dt, r )
  1247. use go_print, only : gol, goErr
  1248. ! --- in/out --------------------------------
  1249. type(TIncrDate), intent(in) :: dt
  1250. real, intent(in) :: r
  1251. ! --- const -----------------------------------
  1252. character(len=*), parameter :: rname = mname//'/dt_div_r'
  1253. ! --- local ---------------------------------
  1254. integer :: status
  1255. real :: rat
  1256. integer :: intg
  1257. real :: frac
  1258. ! --- begin ---------------------------------
  1259. call Check( dt, status )
  1260. IF_NOTOK_RETURN(dt_div_r%status=1)
  1261. ! days:
  1262. rat = dt%day / r
  1263. intg = floor( rat )
  1264. frac = rat - intg
  1265. dt_div_r = IncrDate( day=intg )
  1266. ! hours:
  1267. rat = dt%hour / r + frac*24
  1268. intg = floor( rat )
  1269. frac = rat - intg
  1270. call Set( dt_div_r, hour=intg )
  1271. ! mins:
  1272. rat = dt%min / r + frac*60
  1273. intg = floor( rat )
  1274. frac = rat - intg
  1275. call Set( dt_div_r, min=intg )
  1276. ! seconds:
  1277. rat = dt%sec / r + frac*60
  1278. intg = floor( rat )
  1279. frac = rat - intg
  1280. call Set( dt_div_r, sec=intg )
  1281. ! miliseconds:
  1282. rat = dt%mili / r + frac*1000
  1283. intg = floor( rat )
  1284. frac = rat - intg
  1285. call Set( dt_div_r, mili=intg )
  1286. end function dt_div_r
  1287. ! *
  1288. type(TIncrDate) function dt_div_i( dt, i )
  1289. ! --- in/out --------------------------------
  1290. type(TIncrDate), intent(in) :: dt
  1291. integer, intent(in) :: i
  1292. ! --- begin ---------------------------------
  1293. dt_div_i = dt / (i*1.0)
  1294. end function dt_div_i
  1295. ! ************************************************
  1296. ! ***
  1297. ! *** logical operators
  1298. ! ***
  1299. ! ************************************************
  1300. logical function date_IsAnyDate( t )
  1301. ! --- in/out -------------------------------
  1302. type(TDate), intent(in) :: t
  1303. ! --- begin --------------------------------
  1304. date_IsAnyDate = t%calender == 'any'
  1305. end function date_IsAnyDate
  1306. ! *** date1 == date2
  1307. logical function date_eq_date( t1, t2 )
  1308. use go_print, only : gol, goErr
  1309. ! --- in/out --------------------------------
  1310. type(TDate), intent(in) :: t1
  1311. type(TDate), intent(in) :: t2
  1312. ! --- const -----------------------------------
  1313. character(len=*), parameter :: rname = mname//'/date_eq_date'
  1314. ! --- local -----------------------------------
  1315. integer :: status
  1316. ! --- begin ---------------------------------
  1317. call Check( t1, status )
  1318. IF_NOTOK_RETURN(date_eq_date=.false.)
  1319. call Check( t2, status )
  1320. IF_NOTOK_RETURN(date_eq_date=.false.)
  1321. ! any date ? always equal
  1322. if ( (t1%calender == 'any') .or. (t2%calender == 'any') ) then
  1323. date_eq_date = .true.
  1324. return
  1325. end if
  1326. ! compare values
  1327. date_eq_date = &
  1328. ( t1%year == t2%year ) .and. &
  1329. ( t1%month == t2%month ) .and. &
  1330. ( t1%day == t2%day ) .and. &
  1331. ( t1%zone == t2%zone ) .and. &
  1332. ( t1%hour == t2%hour ) .and. &
  1333. ( t1%min == t2%min ) .and. &
  1334. ( t1%sec == t2%sec ) .and. &
  1335. ( t1%mili == t2%mili )
  1336. end function date_eq_date
  1337. ! *** date1 /= date2
  1338. logical function date_ne_date( t1, t2 )
  1339. ! --- in/out --------------------------------
  1340. type(TDate), intent(in) :: t1
  1341. type(TDate), intent(in) :: t2
  1342. ! --- const -----------------------------------
  1343. character(len=*), parameter :: rname = mname//'/date_ne_date'
  1344. ! --- begin ---------------------------------
  1345. date_ne_date = .not. ( t1 == t2 )
  1346. end function date_ne_date
  1347. ! *** date1 > date2
  1348. logical function date_gt_date( t1, t2 )
  1349. use go_print, only : gol, goErr
  1350. ! --- in/out --------------------------------
  1351. type(TDate), intent(in) :: t1
  1352. type(TDate), intent(in) :: t2
  1353. ! --- const -----------------------------------
  1354. character(len=*), parameter :: rname = mname//'/date_gt_date'
  1355. ! --- local -----------------------------------
  1356. integer :: status
  1357. ! --- begin ---------------------------------
  1358. call Check( t1, status )
  1359. IF_NOTOK_RETURN(date_gt_date=.false.)
  1360. call Check( t2, status )
  1361. IF_NOTOK_RETURN(date_gt_date=.false.)
  1362. ! any date ? always true
  1363. if ( (t1%calender == 'any') .or. (t2%calender == 'any') ) then
  1364. date_gt_date = .true.
  1365. return
  1366. end if
  1367. if ( t1%year > t2%year ) then
  1368. date_gt_date = .true.
  1369. return
  1370. else if ( t1%year < t2%year ) then
  1371. date_gt_date = .false.
  1372. return
  1373. end if
  1374. if ( t1%month > t2%month ) then
  1375. date_gt_date = .true.
  1376. return
  1377. else if ( t1%month < t2%month ) then
  1378. date_gt_date = .false.
  1379. return
  1380. end if
  1381. if ( t1%day > t2%day ) then
  1382. date_gt_date = .true.
  1383. return
  1384. else if ( t1%day < t2%day ) then
  1385. date_gt_date = .false.
  1386. return
  1387. end if
  1388. if ( t1%hour > t2%hour ) then
  1389. date_gt_date = .true.
  1390. return
  1391. else if ( t1%hour < t2%hour ) then
  1392. date_gt_date = .false.
  1393. return
  1394. end if
  1395. if ( t1%min > t2%min ) then
  1396. date_gt_date = .true.
  1397. return
  1398. else if ( t1%min < t2%min ) then
  1399. date_gt_date = .false.
  1400. return
  1401. end if
  1402. if ( t1%sec > t2%sec ) then
  1403. date_gt_date = .true.
  1404. return
  1405. else if ( t1%sec < t2%sec ) then
  1406. date_gt_date = .false.
  1407. return
  1408. end if
  1409. if ( t1%mili > t2%mili ) then
  1410. date_gt_date = .true.
  1411. return
  1412. else if ( t1%mili < t2%mili ) then
  1413. date_gt_date = .false.
  1414. return
  1415. end if
  1416. ! all fields are equal ...
  1417. date_gt_date = .false.
  1418. end function date_gt_date
  1419. ! *** date1 < date2
  1420. logical function date_lt_date( t1, t2 )
  1421. ! --- in/out --------------------------------
  1422. type(TDate), intent(in) :: t1
  1423. type(TDate), intent(in) :: t2
  1424. ! --- begin ---------------------------------
  1425. date_lt_date = (.not.( ( t1 == t2 ) .or. ( t1 > t2 ) )) .or. IsAnyDate(t1) .or. IsAnyDate(t2)
  1426. end function date_lt_date
  1427. ! *** date1 >= date2 ************************
  1428. logical function date_ge_date( t1, t2 )
  1429. ! --- in/out --------------------------------
  1430. type(TDate), intent(in) :: t1
  1431. type(TDate), intent(in) :: t2
  1432. ! --- begin ---------------------------------
  1433. date_ge_date = ( t1 == t2 ) .or. ( t1 > t2 ) .or. IsAnyDate(t1) .or. IsAnyDate(t2)
  1434. end function date_ge_date
  1435. ! *** date1 <= date2 ************************
  1436. logical function date_le_date( t1, t2 )
  1437. ! --- in/out --------------------------------
  1438. type(TDate), intent(in) :: t1
  1439. type(TDate), intent(in) :: t2
  1440. ! --- begin ---------------------------------
  1441. date_le_date = (.not. ( t1 > t2 )) .or. IsAnyDate(t1) .or. IsAnyDate(t2)
  1442. end function date_le_date
  1443. ! ***********************************************
  1444. ! ***
  1445. ! *** totals
  1446. ! ***
  1447. ! ***********************************************
  1448. real function date_rTotal( t, unit )
  1449. use go_print, only : gol, goErr
  1450. ! --- in/out ----------------------------
  1451. type(TDate), intent(in) :: t
  1452. character(len=*), intent(in) :: unit
  1453. ! --- const -----------------------------------
  1454. character(len=*), parameter :: rname = mname//'/date_rTotal'
  1455. ! --- local -----------------------------------
  1456. integer :: status
  1457. real :: nday
  1458. integer :: iyear
  1459. ! --- begin -----------------------------
  1460. call Check( t, status )
  1461. IF_NOTOK_RETURN(date_rTotal=-1.0)
  1462. ! not all arguments are possible ...
  1463. select case ( t%calender )
  1464. case ( 'wall', 'greg', '366', '365' )
  1465. select case ( unit )
  1466. case ( 'year' )
  1467. if ( any( (/t%month,t%day,t%hour,t%min,t%sec,t%mili/) /= 0 ) ) then
  1468. write (gol,'("do not know how to count total:")'); call goErr
  1469. write (gol,'(" unit : ",a)') unit; call goErr
  1470. call wrtgol( ' t : ', t ); call goErr
  1471. write (gol,'("in ",a)') rname; call goErr; date_rTotal=-1; return
  1472. end if
  1473. case ( 'month' )
  1474. if ( any( (/t%day,t%hour,t%min,t%sec,t%mili/) /= 0 ) ) then
  1475. write (gol,'("do not know how to count total:")'); call goErr
  1476. write (gol,'(" unit : ",a)') unit; call goErr
  1477. call wrtgol( ' t : ', t ); call goErr
  1478. write (gol,'("in ",a)') rname; call goErr; date_rTotal=-1; return
  1479. end if
  1480. end select
  1481. case ( 'incr' )
  1482. select case ( unit )
  1483. case ( 'year', 'month' )
  1484. write (gol,'("do not know how to count total in incremental date:")') unit; call goErr
  1485. write (gol,'(" unit : ",a)') unit; call goErr
  1486. call wrtgol( ' t : ', t ); call goErr
  1487. write (gol,'("in ",a)') rname; call goErr; date_rTotal=-1; return
  1488. end select
  1489. end select
  1490. ! precount total number of days for some of the units:
  1491. select case ( unit )
  1492. case ( 'day', 'hour', 'min', 'sec', 'mili' )
  1493. nday = 0.0
  1494. do iyear = 1, t%year-1
  1495. nday = nday + calc_days_in_year(t%calender,iyear)
  1496. end do
  1497. nday = nday + DayNumber( t ) - 1
  1498. end select
  1499. ! count time units:
  1500. select case ( unit )
  1501. case ( 'year' )
  1502. ! set 'nday' to a reference length of the year;
  1503. ! if this length is not constant during the years, the
  1504. ! values of t%month etc have been checked to be zero:
  1505. nday = days_in_year(t) * 1.0
  1506. ! count fractional years:
  1507. date_rTotal = t%year + &
  1508. t%month / 12.0 + &
  1509. t%day / nday + &
  1510. t%hour / nday / 24.0 + &
  1511. t%min / nday / 24.0 / 60.0 + &
  1512. t%sec / nday / 24.0 / 60.0 / 60.0 + &
  1513. t%mili / nday / 24.0 / 60.0 / 60.0 / 1000.0
  1514. case ( 'month' )
  1515. ! set 'nday' to a reference length of the month;
  1516. ! if this length is not constant during the years, the
  1517. ! values of t%day etc been checked to be zero:
  1518. nday = days_in_month(t) * 1.0
  1519. ! count fractional months:
  1520. date_rTotal = t%year * 12.0 + &
  1521. t%month + &
  1522. t%day / nday + &
  1523. t%hour / nday / 24.0 + &
  1524. t%min / nday / 24.0 / 60.0 + &
  1525. t%sec / nday / 24.0 / 60.0 / 60.0 + &
  1526. t%mili / nday / 24.0 / 60.0 / 60.0 / 1000.0
  1527. case ( 'day' )
  1528. ! 'nday' has been set to the total number of days from 0 to t;
  1529. ! count fractional months:
  1530. date_rTotal = nday + &
  1531. t%hour / 24.0 + &
  1532. t%min / 24.0 / 60.0 + &
  1533. t%sec / 24.0 / 60.0 / 60.0 + &
  1534. t%mili / 24.0 / 60.0 / 60.0 / 1000.0
  1535. case ( 'hour' )
  1536. ! 'nday' has been set to the total number of days from 0 to t;
  1537. ! count fractional hours:
  1538. date_rTotal = nday * 24.0 + &
  1539. t%hour + &
  1540. t%min / 60.0 + &
  1541. t%sec / 60.0 / 60.0 + &
  1542. t%mili / 60.0 / 60.0 / 1000.0
  1543. case ( 'min' )
  1544. ! 'nday' has been set to the total number of days from 0 to t;
  1545. ! count fractional minutes:
  1546. date_rTotal = nday * 24.0 * 60.0 + &
  1547. t%hour * 60.0 + &
  1548. t%min + &
  1549. t%sec / 60.0 + &
  1550. t%mili / 60.0 / 1000.0
  1551. case ( 'sec' )
  1552. ! 'nday' has been set to the total number of days from 0 to t;
  1553. ! count fractional seconds:
  1554. date_rTotal = nday * 24.0 * 60.0 * 60.0 + &
  1555. t%hour * 60.0 * 60.0 + &
  1556. t%min * 60.0 + &
  1557. t%sec + &
  1558. t%mili / 1000.0
  1559. case ( 'mili' )
  1560. ! 'nday' has been set to the total number of days from 0 to t;
  1561. ! count fractional mili seconds:
  1562. date_rTotal = nday * 24.0 * 60.0 * 6.00 * 1000.0 + &
  1563. t%hour * 60.0 * 60.0 * 1000.0 + &
  1564. t%min * 60.0 * 1000.0 + &
  1565. t%sec * 1000.0 + &
  1566. t%mili
  1567. case default
  1568. write (gol,'("do not know how to count time in unit : ",a)') trim(unit); call goErr
  1569. write (gol,'("in ",a)') rname; call goErr; date_rTotal=-1.0; return
  1570. end select
  1571. end function date_rTotal
  1572. ! ***
  1573. real function incr_rTotal( dt, unit )
  1574. use go_print, only : gol, goErr
  1575. ! --- in/out ----------------------------
  1576. type(TIncrDate), intent(in) :: dt
  1577. character(len=*), intent(in) :: unit
  1578. ! --- const -----------------------------------
  1579. character(len=*), parameter :: rname = mname//'/incr_rTotal'
  1580. ! --- local -----------------------------------
  1581. integer :: status
  1582. ! --- begin -----------------------------
  1583. call Check( dt, status )
  1584. IF_NOTOK_RETURN(incr_rTotal=-1.0)
  1585. ! count time units:
  1586. select case ( unit )
  1587. case ( 'day' )
  1588. ! 'nday' has been set to the total number of days from 0 to t;
  1589. ! count fractional months:
  1590. incr_rTotal = dt%day + &
  1591. dt%hour / 24.0 + &
  1592. dt%min / 24.0 / 60.0 + &
  1593. dt%sec / 24.0 / 60.0 / 60.0 + &
  1594. dt%mili / 24.0 / 60.0 / 60.0 / 1000.0
  1595. case ( 'hour' )
  1596. ! 'nday' has been set to the total number of days from 0 to t;
  1597. ! count fractional hours:
  1598. incr_rTotal = dt%day * 24.0 + &
  1599. dt%hour + &
  1600. dt%min / 60.0 + &
  1601. dt%sec / 60.0 / 60.0 + &
  1602. dt%mili / 60.0 / 60.0 / 1000.0
  1603. case ( 'min' )
  1604. ! 'nday' has been set to the total number of days from 0 to t;
  1605. ! count fractional minutes:
  1606. incr_rTotal = dt%day * 24.0 * 60.0 + &
  1607. dt%hour * 60.0 + &
  1608. dt%min + &
  1609. dt%sec / 60.0 + &
  1610. dt%mili / 60.0 / 1000.0
  1611. case ( 'sec' )
  1612. ! 'nday' has been set to the total number of days from 0 to t;
  1613. ! count fractional seconds:
  1614. incr_rTotal = dt%day * 24.0 * 60.0 * 60.0 + &
  1615. dt%hour * 60.0 * 60.0 + &
  1616. dt%min * 60.0 + &
  1617. dt%sec + &
  1618. dt%mili / 1000.0
  1619. case ( 'mili' )
  1620. ! 'nday' has been set to the total number of days from 0 to t;
  1621. ! count fractional mili seconds:
  1622. incr_rTotal = dt%day * 24.0 * 60.0 * 6.00 * 1000.0 + &
  1623. dt%hour * 60.0 * 60.0 * 1000.0 + &
  1624. dt%min * 60.0 * 1000.0 + &
  1625. dt%sec * 1000.0 + &
  1626. dt%mili
  1627. case default
  1628. write (gol,'("do not know how to count time in unit : ",a)') trim(unit); call goErr
  1629. write (gol,'("in ",a)') rname; call goErr; incr_rTotal=-1.0; return
  1630. end select
  1631. end function incr_rTotal
  1632. ! ***
  1633. integer function date_iTotal( t, unit )
  1634. use go_print, only : gol, goErr
  1635. ! --- in/out ----------------------------
  1636. type(TDate), intent(in) :: t
  1637. character(len=*), intent(in) :: unit
  1638. ! --- const -----------------------------------
  1639. character(len=*), parameter :: rname = mname//'/date_iTotal'
  1640. ! --- local -----------------------------
  1641. integer :: status
  1642. real :: rtot
  1643. integer :: itot
  1644. ! --- begin -----------------------------
  1645. call Check( t, status )
  1646. IF_NOTOK_RETURN(date_iTotal=-1)
  1647. ! determine total some as a real value:
  1648. rtot = rTotal( t, unit )
  1649. ! round to integer value:
  1650. itot = nint(rtot)
  1651. ! result should be pure integer ....
  1652. if ( itot*1.0 == rtot ) then
  1653. date_iTotal = itot
  1654. else
  1655. write (gol,'("date does not contain integer total:")'); call goErr
  1656. write (gol,'(" unit : ",a)') trim(unit); call goErr
  1657. call wrtgol( ' t : ', t ); call goErr
  1658. write (gol,'("in ",a)') rname; call goErr; date_iTotal=-1; return
  1659. end if
  1660. end function date_iTotal
  1661. ! ***
  1662. integer function incrdate_iTotal( dt, unit )
  1663. use go_print, only : gol, goErr
  1664. ! --- in/out ----------------------------
  1665. type(TIncrDate), intent(in) :: dt
  1666. character(len=*), intent(in) :: unit
  1667. ! --- const -----------------------------------
  1668. character(len=*), parameter :: rname = mname//'/incrdate_iTotal'
  1669. ! --- local -----------------------------
  1670. integer :: status
  1671. real :: rtot
  1672. integer :: itot
  1673. ! --- begin -----------------------------
  1674. call Check( dt, status )
  1675. IF_NOTOK_RETURN(incrdate_iTotal=-1)
  1676. ! determine total some as a real value:
  1677. rtot = rTotal( dt, unit )
  1678. ! round to integer value:
  1679. itot = nint(rtot)
  1680. ! result should be pure integer ....
  1681. if ( itot*1.0 == rtot ) then
  1682. incrdate_iTotal = itot
  1683. else
  1684. write (gol,'("date does not contain integer total:")'); call goErr
  1685. write (gol,'(" unit : ",a)') trim(unit); call goErr
  1686. call wrtgol( ' dt : ', dt ); call goErr
  1687. write (gol,'("in ",a)') rname; call goErr; incrdate_iTotal=-1; return
  1688. end if
  1689. end function incrdate_iTotal
  1690. ! ***********************************************
  1691. ! ***
  1692. ! *** interpolation
  1693. ! ***
  1694. ! ***********************************************
  1695. !
  1696. ! Return coeff such that
  1697. ! t = alfa1 * t1 + alfa2 * t2
  1698. !
  1699. subroutine date_InterpolFractions( t, t1, t2, alfa1, alfa2, status )
  1700. use go_print, only : gol, goErr
  1701. ! --- in/out -----------------------------
  1702. type(TDate), intent(in) :: t
  1703. type(TDate), intent(in) :: t1
  1704. type(TDate), intent(in) :: t2
  1705. real, intent(out) :: alfa1
  1706. real, intent(out) :: alfa2
  1707. integer, intent(out) :: status
  1708. ! --- const ----------------------------------
  1709. character(len=*), parameter :: rname = mname//'/date_InterpolFractions'
  1710. ! --- local ------------------------------
  1711. real :: ds, ds1
  1712. ! --- begin ------------------------------
  1713. ! check ...
  1714. if ( t1 > t2 ) then
  1715. write (gol,'("required interval [t1,t2] :")'); call goErr
  1716. call wrtgol( ' t1 = ', t1 ); call goErr
  1717. call wrtgol( ' t2 = ', t2 ); call goErr
  1718. write (gol,'("in ",a)') rname; call goErr; status=1; return
  1719. end if
  1720. ! check ...
  1721. if ( (t < t1) .or. (t > t2) ) then
  1722. write (gol,'("t not in [t1,t2] :")'); call goErr
  1723. call wrtgol( ' t = ', t ); call goErr
  1724. call wrtgol( ' t1 = ', t1 ); call goErr
  1725. call wrtgol( ' t2 = ', t2 ); call goErr
  1726. write (gol,'("in ",a)') rname; call goErr; status=1; return
  1727. end if
  1728. ! compute differences in seconds:
  1729. ds = rTotal( t2 - t1, 'sec' )
  1730. ds1 = rTotal( t - t1, 'sec' )
  1731. ! return fractions
  1732. if ( abs(ds) < tiny(ds) ) then
  1733. alfa2 = 0.5
  1734. else
  1735. alfa2 = ds1 / ds
  1736. end if
  1737. alfa1 = 1.0 - alfa2
  1738. end subroutine date_InterpolFractions
  1739. ! ***********************************************
  1740. ! ***
  1741. ! *** print
  1742. ! ***
  1743. ! ***********************************************
  1744. #ifdef PRINT_MINU
  1745. #define PRINT_LEN 29
  1746. #else
  1747. #define PRINT_LEN 36
  1748. #endif
  1749. character(len=PRINT_LEN) function date_Pretty( t )
  1750. ! --- in/out -------------------------
  1751. type(TDate), intent(in) :: t
  1752. ! --- const --------------------------
  1753. character(len=3), parameter :: month_name(12) = &
  1754. (/ 'jan','feb','mar','apr','may','jun', &
  1755. 'jul','aug','sep','oct','nov','dec' /)
  1756. ! --- local --------------------------
  1757. integer :: zone_abs, zone_hour, zone_min
  1758. character(len=1) :: zone_sign
  1759. character(len=PRINT_LEN) :: s
  1760. ! --- begin --------------------------
  1761. select case ( t%calender )
  1762. case ( 'wall' )
  1763. if ( t%zone < 0 ) then
  1764. zone_sign = '-'
  1765. else
  1766. zone_sign = '+'
  1767. end if
  1768. zone_abs = abs(t%zone)
  1769. zone_hour = floor(zone_abs/60.0)
  1770. zone_min = zone_abs - zone_hour*60
  1771. write (s,'(i2,":",i2.2,":",i2.2,":",i3.3, &
  1772. & " ",i2.2," ",a3," ",i4.4, &
  1773. & " (GMT",a1,i2.2,":",i2.2,")")') &
  1774. t%hour, t%min, t%sec, t%mili, &
  1775. t%day, month_name(t%month), t%year, &
  1776. zone_sign, zone_hour, zone_min
  1777. case ( 'greg', 'PRINT_LEN6', 'PRINT_LEN5', 'PRINT_LEN0', 'any' )
  1778. #ifdef PRINT_MINU
  1779. write (s,'(i4.4,"/",i2.2,"/",i2.2," ",i2,":",i2.2)') &
  1780. t%year, t%month, t%day, t%hour, t%min
  1781. #else
  1782. write (s,'(i4.4,"/",i2.2,"/",i2.2," ",i2,":",i2.2,":",i2.2,":",i3.3)') &
  1783. t%year, t%month, t%day, t%hour, t%min, t%sec, t%mili
  1784. #endif
  1785. case default
  1786. s = 'no-calender'
  1787. end select
  1788. date_Pretty = s
  1789. end function date_Pretty
  1790. ! *
  1791. character(len=PRINT_LEN) function incrdate_Pretty( dt )
  1792. ! --- in/out -------------------------
  1793. type(TIncrDate), intent(in) :: dt
  1794. ! --- local --------------------------
  1795. integer :: zone_abs, zone_hour, zone_min
  1796. character(len=1) :: zone_sign
  1797. character(len=PRINT_LEN) :: s
  1798. ! --- begin --------------------------
  1799. #ifdef PRINT_MINU
  1800. write (s,'(i5," days ",i2,":",i2.2,":",i2.2,":",i3.3)') &
  1801. dt%day, dt%hour, dt%min, dt%sec, dt%mili
  1802. #else
  1803. write (s,'(i5," days ",i2,":",i2.2)') &
  1804. dt%day, dt%hour, dt%min
  1805. #endif
  1806. incrdate_Pretty = s
  1807. end function incrdate_Pretty
  1808. ! *
  1809. subroutine wrtgol_t( msg, t )
  1810. use go_print, only : gol
  1811. ! --- in/out -----------------------------------
  1812. character(len=*), intent(in) :: msg
  1813. type(TDate), intent(in) :: t
  1814. ! --- local ---------------------------------
  1815. character(len=PRINT_LEN) :: s
  1816. ! --- begin -----------------------------------
  1817. s = date_Pretty( t )
  1818. write (gol,'(a,a)') msg, trim(s)
  1819. end subroutine wrtgol_t
  1820. ! *
  1821. subroutine wrtgol_dt( msg, dt )
  1822. use go_print, only : gol
  1823. ! --- in/out -----------------------------------
  1824. character(len=*), intent(in) :: msg
  1825. type(TIncrDate), intent(in) :: dt
  1826. ! --- local ---------------------------------
  1827. character(len=PRINT_LEN) :: s
  1828. ! --- begin -----------------------------------
  1829. s = incrdate_Pretty( dt )
  1830. write (gol,'(a,a)') msg, trim(s)
  1831. end subroutine wrtgol_dt
  1832. ! *
  1833. subroutine wrtgol_t1_t2( msg, t, msg2, t2 )
  1834. use go_print, only : gol
  1835. ! --- in/out -----------------------------------
  1836. character(len=*), intent(in) :: msg
  1837. type(TDate), intent(in) :: t
  1838. character(len=*), intent(in) :: msg2
  1839. type(TDate), intent(in) :: t2
  1840. ! --- local ---------------------------------
  1841. character(len=PRINT_LEN) :: s
  1842. character(len=PRINT_LEN) :: s2
  1843. ! --- begin -----------------------------------
  1844. s = date_Pretty( t )
  1845. s2 = date_Pretty( t2 )
  1846. write (gol,'(a,a,a,a)') msg, trim(s), msg2, trim(s2)
  1847. end subroutine wrtgol_t1_t2
  1848. ! *
  1849. subroutine wrtgol_t1_t2_t3( msg, t, msg2, t2, msg3, t3 )
  1850. use go_print, only : gol
  1851. ! --- in/out -----------------------------------
  1852. character(len=*), intent(in) :: msg
  1853. type(TDate), intent(in) :: t
  1854. character(len=*), intent(in) :: msg2
  1855. type(TDate), intent(in) :: t2
  1856. character(len=*), intent(in) :: msg3
  1857. type(TDate), intent(in) :: t3
  1858. ! --- local ---------------------------------
  1859. character(len=PRINT_LEN) :: s
  1860. character(len=PRINT_LEN) :: s2
  1861. character(len=PRINT_LEN) :: s3
  1862. ! --- begin -----------------------------------
  1863. s = date_Pretty( t )
  1864. s2 = date_Pretty( t2 )
  1865. s3 = date_Pretty( t3 )
  1866. write (gol,'(a,a,a,a,a,a)') msg, trim(s), msg2, trim(s2), msg3, trim(s3)
  1867. end subroutine wrtgol_t1_t2_t3
  1868. end module GO_Date