1 | #!/bin/ksh |
---|
2 | |
---|
3 | #************************************************************** |
---|
4 | # Author: Sebastien Denvil |
---|
5 | # Contact: Sebastien.Denvil__at__ipsl.jussieu.fr |
---|
6 | # $Revision:: $ Revision of last commit |
---|
7 | # $Author:: $ Author of last commit |
---|
8 | # $Date:: $ Date of last commit |
---|
9 | # IPSL (2006) |
---|
10 | # This software is governed by the CeCILL licence see libIGCM/libIGCM_CeCILL.LIC |
---|
11 | # |
---|
12 | #************************************************************** |
---|
13 | |
---|
14 | #================================================== |
---|
15 | # The documentation of this file can be automatically generated |
---|
16 | # if you use the prefix #D- for comments to be extracted. |
---|
17 | # Extract with command: cat lib* | grep "^#D-" | cut -c "4-" |
---|
18 | #================================================== |
---|
19 | |
---|
20 | #D-#================================================================== |
---|
21 | #D-libIGCM_date |
---|
22 | #D-This ksh library handles date calculs and convertions in different calendars. |
---|
23 | #D- types of calendars are possible : |
---|
24 | #D- |
---|
25 | #D- - leap|gregorian|standard (other name leap) : |
---|
26 | #D- The normal calendar. The time origin for the |
---|
27 | #D- julian day in this case is 24 Nov -4713. |
---|
28 | #D- - noleap|365_day : |
---|
29 | #D- A 365 day year without leap years. |
---|
30 | #D- - all_leap|366_day : |
---|
31 | #D- A 366 day year with only leap years. |
---|
32 | #D- - 360d|360_day : |
---|
33 | #D- Year of 360 days with month of equal length. |
---|
34 | |
---|
35 | # Number of digit in the year |
---|
36 | typeset -r dY=${dY:=4} |
---|
37 | #typeset -r MaxpY=$( echo "10^"$((dY+1)) | bc -l ) |
---|
38 | # Number of digit in non-human date representation |
---|
39 | typeset -r pY=$(( dY+4 )) |
---|
40 | |
---|
41 | #================================================================== |
---|
42 | function IGCM_date_YearDigit |
---|
43 | { |
---|
44 | IGCM_debug_PushStack "IGCM_date_YearDigit" $@ |
---|
45 | |
---|
46 | NUM=$(( 10#${1} )) |
---|
47 | echo $( gawk "BEGIN { printf \"%0${dY}d\",${NUM} }" ) |
---|
48 | |
---|
49 | IGCM_debug_PopStack "IGCM_date_YearDigit" |
---|
50 | } |
---|
51 | |
---|
52 | #================================================================== |
---|
53 | function IGCM_date_GregorianDigit |
---|
54 | { |
---|
55 | IGCM_debug_PushStack "IGCM_date_GregorianDigit" $@ |
---|
56 | |
---|
57 | NUM=$(( 10#${1} )) |
---|
58 | echo $( gawk "BEGIN { printf \"%0${pY}d\",${NUM} }" ) |
---|
59 | |
---|
60 | IGCM_debug_PopStack "IGCM_date_GregorianDigit" |
---|
61 | } |
---|
62 | |
---|
63 | #================================================================== |
---|
64 | function IGCM_date_HumanDigit |
---|
65 | { |
---|
66 | IGCM_debug_PushStack "IGCM_date_HumanDigit" $@ |
---|
67 | |
---|
68 | echo $( IGCM_date_GregorianDigit $( print ${1} | sed 's/-//g' ) ) \ |
---|
69 | | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1-\2-\3/" |
---|
70 | |
---|
71 | IGCM_debug_PopStack "IGCM_date_HumanDigit" |
---|
72 | } |
---|
73 | |
---|
74 | #================================================================== |
---|
75 | function IGCM_date_SupressZeros |
---|
76 | { |
---|
77 | IGCM_debug_PushStack "IGCM_date_SupressZeros" $@ |
---|
78 | echo $( print ${1} | sed -e "s/0*//" ) |
---|
79 | IGCM_debug_PopStack "IGCM_date_SupressZeros" |
---|
80 | } |
---|
81 | |
---|
82 | #================================================================== |
---|
83 | function IGCM_date_ConvertFormatToGregorian |
---|
84 | { |
---|
85 | IGCM_debug_PushStack "IGCM_date_ConvertFormatToGregorian" $@ |
---|
86 | |
---|
87 | # from a yyyy-mm-dd date format return |
---|
88 | # a yyymmdd date format |
---|
89 | # usage IGCM_date_ConvertFormat yyyy-mm-dd |
---|
90 | |
---|
91 | # if there is no argument on the command line, |
---|
92 | # then assume that a y-m-d formated date is being |
---|
93 | # piped in |
---|
94 | typeset ymd |
---|
95 | if [ $# = 0 ] |
---|
96 | then |
---|
97 | read ymd |
---|
98 | else |
---|
99 | ymd=$1 |
---|
100 | fi |
---|
101 | |
---|
102 | IGCM_date_GregorianDigit $( print ${ymd} | sed 's/-//g' ) |
---|
103 | |
---|
104 | IGCM_debug_PopStack "IGCM_date_ConvertFormatToGregorian" |
---|
105 | } |
---|
106 | |
---|
107 | #================================================================== |
---|
108 | function IGCM_date_ConvertFormatToHuman |
---|
109 | { |
---|
110 | IGCM_debug_PushStack "IGCM_date_ConvertFormatToHuman" $@ |
---|
111 | |
---|
112 | # from a yyyymmdd date format return |
---|
113 | # a yyyy-mm-dd date format |
---|
114 | # usage IGCM_date_ConvertFormat yyyymmdd |
---|
115 | |
---|
116 | # if there is no argument on the command line, |
---|
117 | # then assume that a yyyymmdd formated date is being |
---|
118 | # piped in |
---|
119 | typeset dt |
---|
120 | if [ $# = 0 ] |
---|
121 | then |
---|
122 | read dt |
---|
123 | else |
---|
124 | dt=$1 |
---|
125 | fi |
---|
126 | |
---|
127 | # break the yyyymmdd into separate parts for year, month and day |
---|
128 | echo $( IGCM_date_GregorianDigit ${dt} ) \ |
---|
129 | | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1-\2-\3/" |
---|
130 | |
---|
131 | IGCM_debug_PopStack "IGCM_date_ConvertFormatToHuman" |
---|
132 | } |
---|
133 | |
---|
134 | #================================================================== |
---|
135 | function IGCM_date_GetYearMonth |
---|
136 | { |
---|
137 | IGCM_debug_PushStack "IGCM_date_GetYearMonth" $@ |
---|
138 | |
---|
139 | # from a yyyymmdd date format return |
---|
140 | # a yyyy year and mm month |
---|
141 | # usage IGCM_date_GetYearMonth yyyymmdd year_var month_var |
---|
142 | |
---|
143 | # if there is no argument on the command line, |
---|
144 | # then assume that a yyyymmdd formated date is being |
---|
145 | # piped in |
---|
146 | typeset dt |
---|
147 | if [ $# = 0 ] |
---|
148 | then |
---|
149 | read dt |
---|
150 | else |
---|
151 | dt=$1 |
---|
152 | fi |
---|
153 | |
---|
154 | # break the yyyymmdd into separate parts for year, month and day |
---|
155 | eval $2=$( echo $( IGCM_date_GregorianDigit ${dt} ) \ |
---|
156 | | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1/" ) |
---|
157 | eval $3=$( echo $( IGCM_date_GregorianDigit ${dt} ) \ |
---|
158 | | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\2/" ) |
---|
159 | |
---|
160 | IGCM_debug_PopStack "IGCM_date_GetYearMonth" |
---|
161 | } |
---|
162 | |
---|
163 | #================================================================== |
---|
164 | function IGCM_date_GetYearMonthDay |
---|
165 | { |
---|
166 | IGCM_debug_PushStack "IGCM_date_GetYearMonthDay" $@ |
---|
167 | |
---|
168 | # from a yyyymmdd date format return |
---|
169 | # a yyyy year, mm month and dd day |
---|
170 | # usage IGCM_date_GetYearMonthDay yyyymmdd year_var month_var day_var |
---|
171 | |
---|
172 | # if there is no argument on the command line, |
---|
173 | # then assume that a yyyymmdd formated date is being |
---|
174 | # piped in |
---|
175 | typeset dt |
---|
176 | if [ $# = 0 ] |
---|
177 | then |
---|
178 | read dt |
---|
179 | else |
---|
180 | dt=$1 |
---|
181 | fi |
---|
182 | |
---|
183 | # break the yyyymmdd into separate parts for year, month and day |
---|
184 | eval $2=$( echo $( IGCM_date_GregorianDigit ${dt} ) \ |
---|
185 | | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1/" ) |
---|
186 | eval $3=$( echo $( IGCM_date_GregorianDigit ${dt} ) \ |
---|
187 | | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\2/" ) |
---|
188 | eval $4=$( echo $( IGCM_date_GregorianDigit ${dt} ) \ |
---|
189 | | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\3/" ) |
---|
190 | |
---|
191 | IGCM_debug_PopStack "IGCM_date_GetYearMonthDay" |
---|
192 | } |
---|
193 | |
---|
194 | #D-#================================================================== |
---|
195 | #D-function IGCM_date_DaysInYear |
---|
196 | #D-* Purpose: Return the number of days in a year |
---|
197 | #D-* Usage: IGCM_date_DaysInYear yyyy |
---|
198 | #D- if there is no argument on the command line, |
---|
199 | #D- then assume that a yyyy is being piped in |
---|
200 | #D- |
---|
201 | function IGCM_date_DaysInYear |
---|
202 | { |
---|
203 | # IGCM_debug_PushStack "IGCM_date_DaysInYear" $@ |
---|
204 | # return the number of days in a year |
---|
205 | # usage IGCM_date_DaysInYear yyyy |
---|
206 | |
---|
207 | # What is the calendar : |
---|
208 | case ${config_UserChoices_CalendarType} in |
---|
209 | 360d|360_day) |
---|
210 | if [ X$2 = X ] ; then |
---|
211 | echo 360 |
---|
212 | else |
---|
213 | eval $2=360 > /dev/null 2>&1 |
---|
214 | fi |
---|
215 | # IGCM_debug_PopStack "IGCM_date_DaysInYear" |
---|
216 | return;; |
---|
217 | noleap|365_day) |
---|
218 | if [ X$2 = X ] ; then |
---|
219 | echo 365 |
---|
220 | else |
---|
221 | eval $2=365 > /dev/null 2>&1 |
---|
222 | fi |
---|
223 | |
---|
224 | # IGCM_debug_PopStack "IGCM_date_DaysInYear" |
---|
225 | return;; |
---|
226 | all_leap|366_day) |
---|
227 | if [ X$2 = X ] ; then |
---|
228 | echo 366 |
---|
229 | else |
---|
230 | eval $2=366 > /dev/null 2>&1 |
---|
231 | fi |
---|
232 | |
---|
233 | # IGCM_debug_PopStack "IGCM_date_DaysInYear" |
---|
234 | return;; |
---|
235 | esac |
---|
236 | |
---|
237 | typeset y a |
---|
238 | |
---|
239 | # if there is no argument on the command line, |
---|
240 | # then assume that a yyyy is being piped in |
---|
241 | if [ $# = 0 ] |
---|
242 | then |
---|
243 | read y |
---|
244 | else |
---|
245 | y=$(( 10#${1} )) |
---|
246 | fi |
---|
247 | |
---|
248 | # a year is a leap year if it is even divisible by 4 |
---|
249 | # but not evenly divisible by 100 |
---|
250 | # unless it is evenly divisible by 400 |
---|
251 | |
---|
252 | # if it is evenly divisible by 400 it must be a leap year |
---|
253 | a=$(( $y % 400 )) |
---|
254 | if [ $a = 0 ] |
---|
255 | then |
---|
256 | if [ X$2 = X ] ; then |
---|
257 | echo 366 |
---|
258 | else |
---|
259 | eval $2=366 > /dev/null 2>&1 |
---|
260 | fi |
---|
261 | |
---|
262 | # IGCM_debug_PopStack "IGCM_date_DaysInYear" |
---|
263 | return |
---|
264 | fi |
---|
265 | |
---|
266 | #if it is evenly divisible by 100 it must not be a leap year |
---|
267 | a=$(( $y % 100 )) |
---|
268 | if [ $a = 0 ] |
---|
269 | then |
---|
270 | if [ X$2 = X ] ; then |
---|
271 | echo 365 |
---|
272 | else |
---|
273 | eval $2=365 > /dev/null 2>&1 |
---|
274 | fi |
---|
275 | |
---|
276 | # IGCM_debug_PopStack "IGCM_date_DaysInYear" |
---|
277 | return |
---|
278 | fi |
---|
279 | |
---|
280 | # if it is evenly divisible by 4 it must be a leap year |
---|
281 | a=$(( $y % 4 )) |
---|
282 | if [ $a = 0 ] |
---|
283 | then |
---|
284 | if [ X$2 = X ] ; then |
---|
285 | echo 366 |
---|
286 | else |
---|
287 | eval $2=366 > /dev/null 2>&1 |
---|
288 | fi |
---|
289 | |
---|
290 | # IGCM_debug_PopStack "IGCM_date_DaysInYear" |
---|
291 | return |
---|
292 | fi |
---|
293 | |
---|
294 | # otherwise it is not a leap year |
---|
295 | if [ X$2 = X ] ; then |
---|
296 | echo 365 |
---|
297 | else |
---|
298 | eval $2=365 > /dev/null 2>&1 |
---|
299 | fi |
---|
300 | |
---|
301 | # IGCM_debug_PopStack "IGCM_date_DaysInYear" |
---|
302 | } |
---|
303 | |
---|
304 | #D-#================================================================== |
---|
305 | #D-function IGCM_date_DaysInMonth |
---|
306 | #D-* Purpose: Calculate the number of days in a month |
---|
307 | #D-* Usage: IGCM_date_DaysInMonth yyyy mm |
---|
308 | #D- or IGCM_date_DaysInMonth yyyymmdd |
---|
309 | #D- if there are no command line arguments then |
---|
310 | #D- assume that a yyyymmdd is being piped in and read the value. |
---|
311 | #D- if there is only one argument assume it is a yyyymmdd on the command line |
---|
312 | #D- other wise it is a yyyy and mm on the command line |
---|
313 | function IGCM_date_DaysInMonth |
---|
314 | { |
---|
315 | # IGCM_debug_PushStack "IGCM_date_DaysInMonth" $@ |
---|
316 | |
---|
317 | # calculates the number of days in a month |
---|
318 | # usage IGCM_date_DaysInMonth yyyy mm |
---|
319 | # or IGCM_date_DaysInMonth yyyymmdd |
---|
320 | |
---|
321 | # What is the calendar : |
---|
322 | if ( [ "${config_UserChoices_CalendarType}" = "360d" ] || [ "${config_UserChoices_CalendarType}" = "360_day" ] ) ; then |
---|
323 | if [ X$3 = X ] ; then |
---|
324 | echo 30 |
---|
325 | else |
---|
326 | eval $3=30 > /dev/null 2>&1 |
---|
327 | fi |
---|
328 | |
---|
329 | # IGCM_debug_PopStack "IGCM_date_DaysInMonth" |
---|
330 | return |
---|
331 | fi |
---|
332 | |
---|
333 | typeset ymd y m |
---|
334 | |
---|
335 | # if there are no command line arguments then assume that a yyyymmdd is being |
---|
336 | # piped in and read the value. |
---|
337 | # if there is only one argument assume it is a yyyymmdd on the command line |
---|
338 | # other wise it is a yyyy and mm on the command line |
---|
339 | if [ $# = 0 ] |
---|
340 | then |
---|
341 | read ymd |
---|
342 | elif [ $# = 1 ] |
---|
343 | then |
---|
344 | ymd=$1 |
---|
345 | else |
---|
346 | ymd=$(( ( $1 * 10000 ) + ( $2 * 100 ) + 1 )) |
---|
347 | fi |
---|
348 | |
---|
349 | # extract the year and the month |
---|
350 | y=$(( $ymd / 10000 )) ; |
---|
351 | m=$(( ( $ymd % 10000 ) / 100 )) ; |
---|
352 | |
---|
353 | # 30 days hath september etc. |
---|
354 | case $m in |
---|
355 | 1|3|5|7|8|10|12) |
---|
356 | if [ X$3 = X ] ; then |
---|
357 | echo 31 |
---|
358 | else |
---|
359 | eval $3=31 > /dev/null 2>&1 |
---|
360 | fi |
---|
361 | |
---|
362 | # IGCM_debug_PopStack "IGCM_date_DaysInMonth" |
---|
363 | return ;; |
---|
364 | 4|6|9|11) |
---|
365 | if [ X$3 = X ] ; then |
---|
366 | echo 30 |
---|
367 | else |
---|
368 | eval $3=30 > /dev/null 2>&1 |
---|
369 | fi |
---|
370 | |
---|
371 | # IGCM_debug_PopStack "IGCM_date_DaysInMonth" |
---|
372 | return ;; |
---|
373 | *) ;; |
---|
374 | esac |
---|
375 | |
---|
376 | # except for month 2 which depends on whether the year is a leap year |
---|
377 | # Use IGCM_date_DaysInYear to get the number of days in the year and return a value |
---|
378 | # accordingly. |
---|
379 | IGCM_date_DaysInYear $y diy |
---|
380 | case $diy in |
---|
381 | 365) |
---|
382 | if [ X$3 = X ] ; then |
---|
383 | echo 28 |
---|
384 | else |
---|
385 | eval $3=28 > /dev/null 2>&1 |
---|
386 | fi |
---|
387 | |
---|
388 | # IGCM_debug_PopStack "IGCM_date_DaysInMonth" |
---|
389 | return ;; |
---|
390 | 366) |
---|
391 | if [ X$3 = X ] ; then |
---|
392 | echo 29 |
---|
393 | else |
---|
394 | eval $3=29 > /dev/null 2>&1 |
---|
395 | fi |
---|
396 | |
---|
397 | # IGCM_debug_PopStack "IGCM_date_DaysInMonth" |
---|
398 | return ;; |
---|
399 | esac |
---|
400 | |
---|
401 | # IGCM_debug_PopStack "IGCM_date_DaysInMonth" |
---|
402 | } |
---|
403 | |
---|
404 | #D-#================================================================== |
---|
405 | #D-function IGCM_date_ConvertGregorianDateToJulian |
---|
406 | #D-* Purpose: Convert yyyymmdd to yyyyddd |
---|
407 | #D-* Usage: IGCM_date_ConvertGregorianDateToJulian 19980429 |
---|
408 | #D- if there is no command line argument, then assume that the date |
---|
409 | #D- is coming in on a pipe and use read to collect it |
---|
410 | #D- |
---|
411 | function IGCM_date_ConvertGregorianDateToJulian |
---|
412 | { |
---|
413 | IGCM_debug_PushStack "IGCM_date_ConvertGregorianDateToJulian" $@ |
---|
414 | |
---|
415 | # IGCM_date_ConvertGregorianDateToJulian converts yyyymmdd to yyyyddd |
---|
416 | # usage IGCM_date_ConvertGregorianDateToJulian 19980429 |
---|
417 | |
---|
418 | typeset dt y m d x jul |
---|
419 | |
---|
420 | # if there is no command line argument, then assume that the date |
---|
421 | # is coming in on a pipe and use read to collect it |
---|
422 | if [ $# = 0 ] |
---|
423 | then |
---|
424 | read dt |
---|
425 | else |
---|
426 | dt=$( IGCM_date_SupressZeros $1 ) |
---|
427 | fi |
---|
428 | |
---|
429 | # break the yyyymmdd into separate parts for year, month and day |
---|
430 | y=$(( $dt / 10000 )) |
---|
431 | m=$(( ( $dt % 10000 ) / 100 )) |
---|
432 | d=$(( ( $dt % 100 ) )) |
---|
433 | |
---|
434 | # add the days in each month up to (but not including the month itself) |
---|
435 | # into the days. For example if the date is 19980203 then extract the |
---|
436 | # number of days in January and add it to 03. If the date is June 14, 1998 |
---|
437 | # then extract the number of days in January, February, March, April and May |
---|
438 | # and add them to 14. |
---|
439 | x=1 |
---|
440 | while [ $x -lt $m ] |
---|
441 | do |
---|
442 | IGCM_date_DaysInMonth $y $x md |
---|
443 | d=$(( $d + $md )) |
---|
444 | x=$(( $x + 1 )) |
---|
445 | done |
---|
446 | |
---|
447 | # combine the year and day back together again and you have the julian date. |
---|
448 | jul=$(( ( $y * 1000 ) + $d )) |
---|
449 | echo $jul |
---|
450 | |
---|
451 | IGCM_debug_PopStack "IGCM_date_ConvertGregorianDateToJulian" |
---|
452 | } |
---|
453 | |
---|
454 | #D-#================================================================== |
---|
455 | #D-function IGCM_date_ConvertJulianDateToGregorian() |
---|
456 | #D-* Purpose: Convert yyyyddd to yyyymmdd |
---|
457 | #D-* Usage: IGCM_date_ConvertJulianDateToGregorian 1998213 |
---|
458 | #D- if there is no command line argument, assume one is being |
---|
459 | #D- piped in and read it |
---|
460 | #D- |
---|
461 | function IGCM_date_ConvertJulianDateToGregorian |
---|
462 | { |
---|
463 | IGCM_debug_PushStack "IGCM_date_ConvertJulianDateToGregorian" $@ |
---|
464 | |
---|
465 | # IGCM_date_ConvertJulianDateToGregorian converts yyyyddd to yyyymmdd |
---|
466 | # usage IGCM_date_ConvertJulianDateToGregorian 1998213 |
---|
467 | |
---|
468 | typeset dt y m d grg |
---|
469 | |
---|
470 | # if there is no command line argument, assume one is being |
---|
471 | # piped in and read it |
---|
472 | if [ X$1 = X ] |
---|
473 | then |
---|
474 | read dt |
---|
475 | else |
---|
476 | dt=$1 |
---|
477 | fi |
---|
478 | |
---|
479 | # break apart the year and the days |
---|
480 | y=$(( $dt / 1000 )) |
---|
481 | d=$(( $dt % 1000 )) |
---|
482 | |
---|
483 | # subtract the number of days in each month starting from 1 |
---|
484 | # from the days in the date. When the day goes below 1, you |
---|
485 | # have the current month. Add back the number of days in the |
---|
486 | # month to get the correct day of the month |
---|
487 | m=1 |
---|
488 | while [ $d -gt 0 ] |
---|
489 | do |
---|
490 | IGCM_date_DaysInMonth $y $m md |
---|
491 | d=$(( $d - $md )) |
---|
492 | m=$(( $m + 1 )) |
---|
493 | done |
---|
494 | |
---|
495 | d=$(( $d + $md )) |
---|
496 | |
---|
497 | # the loop steps one past the correct month, so back up the month |
---|
498 | m=$(( $m - 1 )) |
---|
499 | |
---|
500 | # assemble the results into a gregorian date |
---|
501 | grg=$(( ( $y * 10000 ) + ( $m * 100 ) + $d )) |
---|
502 | echo $( IGCM_date_GregorianDigit $grg ) |
---|
503 | |
---|
504 | IGCM_debug_PopStack "IGCM_date_ConvertJulianDateToGregorian" |
---|
505 | } |
---|
506 | |
---|
507 | #D-#================================================================== |
---|
508 | #D-function IGCM_date_AddDaysToJulianDate |
---|
509 | #D-* Purpose: Add days to a yyyyddd formatted date |
---|
510 | #D-* Usage: IGCM_date_AddDaysToJulianDate 1998312 { ,-}14 |
---|
511 | #D- Read the difference from the command lines |
---|
512 | #D- and the date from the command line, or standard input |
---|
513 | #D- |
---|
514 | function IGCM_date_AddDaysToJulianDate |
---|
515 | { |
---|
516 | IGCM_debug_PushStack "IGCM_date_AddDaysToJulianDate" $@ |
---|
517 | |
---|
518 | # IGCM_date_AddDaysToJulianDate adds days to a yyyyddd formatted date |
---|
519 | # usage IGCM_date_AddDaysToJulianDate 1998312 { ,-}14 |
---|
520 | |
---|
521 | typeset dif yd d y |
---|
522 | |
---|
523 | # Read the difference from the command lines |
---|
524 | # and the date from the command line, or standard input |
---|
525 | if [ X$2 = X ] |
---|
526 | then |
---|
527 | dif=$1 |
---|
528 | read yd |
---|
529 | else |
---|
530 | yd=$1 |
---|
531 | dif=$2 |
---|
532 | fi |
---|
533 | |
---|
534 | # Break it into pieces |
---|
535 | d=$(( $yd % 1000 )) |
---|
536 | y=$(( $yd / 1000 )) |
---|
537 | |
---|
538 | # Add the number of days (if days is negative this results is |
---|
539 | # a subtraction) |
---|
540 | d=$(( $d + $dif )) |
---|
541 | |
---|
542 | # Extract the days in the year |
---|
543 | IGCM_date_DaysInYear $y diy |
---|
544 | |
---|
545 | # If the calculated day exceeds the days in the year, |
---|
546 | # add one year to the year and subtract the days in the year from the |
---|
547 | # calculated days. Extract the days in the new year and repeat |
---|
548 | # test until you end up with a day number that falls within the |
---|
549 | # days of the year |
---|
550 | while [ $d -gt $diy ] |
---|
551 | do |
---|
552 | d=$(( $d - $diy )) |
---|
553 | y=$(( $y + 1 )) |
---|
554 | IGCM_date_DaysInYear $y diy |
---|
555 | done |
---|
556 | |
---|
557 | # This is the reverse process. If the calculated number of days |
---|
558 | # is less than 1, move back one year. Extract |
---|
559 | # the days in this year and add the days in the year |
---|
560 | # loop on this test until you end up with a number that |
---|
561 | # falls within the days of the year |
---|
562 | while [ $d -lt 1 ] |
---|
563 | do |
---|
564 | y=$(( $y - 1 )) |
---|
565 | IGCM_date_DaysInYear $y diy |
---|
566 | d=$(( $d + $diy )) |
---|
567 | done |
---|
568 | |
---|
569 | # put the year and day back together and echo the result |
---|
570 | yd=$(( ( $y * 1000 ) + $d )) |
---|
571 | |
---|
572 | echo $yd |
---|
573 | |
---|
574 | IGCM_debug_PopStack "IGCM_date_AddDaysToJulianDate" |
---|
575 | } |
---|
576 | |
---|
577 | #D-#================================================================== |
---|
578 | #D-function IGCM_date_AddDaysToGregorianDate |
---|
579 | #D-* Purpose: Add days to a yyyymmdd formatted date |
---|
580 | #D-* Usage: IGCM_date_AddDaysToGregorianDate 19980312 { ,-}14 |
---|
581 | #D- Read the difference from the command lines |
---|
582 | #D- and the date from the command line, or standard input |
---|
583 | #D- |
---|
584 | function IGCM_date_AddDaysToGregorianDate |
---|
585 | { |
---|
586 | IGCM_debug_PushStack "IGCM_date_AddDaysToGregorianDate" $@ |
---|
587 | |
---|
588 | # IGCM_date_AddDaysToGregorianDate adds days to a yyyymmdd formatted date |
---|
589 | # usage IGCM_date_AddDaysToGregorianDate 19980312 { ,-}14 |
---|
590 | |
---|
591 | # Read the difference from the command lines |
---|
592 | # and the date from the command line, or standard input |
---|
593 | typeset dif yd tmp res |
---|
594 | if [ X$2 = X ] |
---|
595 | then |
---|
596 | dif=$1 |
---|
597 | read yd |
---|
598 | else |
---|
599 | yd=$1 |
---|
600 | dif=$2 |
---|
601 | fi |
---|
602 | |
---|
603 | tmp=$( IGCM_date_ConvertGregorianDateToJulian $yd ) |
---|
604 | tmp=$( IGCM_date_AddDaysToJulianDate $tmp $dif ) |
---|
605 | res=$( IGCM_date_ConvertJulianDateToGregorian $tmp ) |
---|
606 | |
---|
607 | echo $res |
---|
608 | |
---|
609 | IGCM_debug_PopStack "IGCM_date_AddDaysToGregorianDate" |
---|
610 | } |
---|
611 | |
---|
612 | #D-#================================================================== |
---|
613 | #D-function IGCM_date_DaysBetweenJulianDate |
---|
614 | #D-* Purpose: Calculate the days difference between two dates and reports |
---|
615 | #D- the number days as jul1 - jul2 |
---|
616 | #D-* Usage: IGCM_date_DaysBetweenJulianDate jul1 jul2 |
---|
617 | #D- where julian date is in the form yyyyddd |
---|
618 | #D- |
---|
619 | function IGCM_date_DaysBetweenJulianDate |
---|
620 | { |
---|
621 | IGCM_debug_PushStack "IGCM_date_DaysBetweenJulianDate" $@ |
---|
622 | |
---|
623 | # calculates the days difference between two dates and reports |
---|
624 | # the number days as jul1 - jul2 |
---|
625 | # usage IGCM_date_DaysBetweenJulianDate jul1 jul2 |
---|
626 | # where julian date is in the form yyyyddd |
---|
627 | |
---|
628 | usage () { |
---|
629 | echo "Usage:" |
---|
630 | echo " IGCM_date_DaysBetweenJulianDate jul1 jul2" |
---|
631 | echo "" |
---|
632 | echo " Calculates the day difference between" |
---|
633 | echo " two julian dates (jul1 -jul2)" |
---|
634 | echo " where a julian date is in the form of yyyyddd." |
---|
635 | } |
---|
636 | |
---|
637 | if [ $# -lt 2 ]; then |
---|
638 | usage |
---|
639 | IGCM_debug_Exit "IGCM_date_DaysBetweenJulianDate" |
---|
640 | fi |
---|
641 | |
---|
642 | # This process subtracts arg2 from arg1. If arg2 is larger |
---|
643 | # then reverse the arguments. The calculations are done, and |
---|
644 | # then the sign is reversed |
---|
645 | if [ $1 -lt $2 ] |
---|
646 | then |
---|
647 | jul1=$2 |
---|
648 | jul2=$1 |
---|
649 | elif [ $1 -gt $2 ] |
---|
650 | then |
---|
651 | jul1=$1 |
---|
652 | jul2=$2 |
---|
653 | else |
---|
654 | echo 0 |
---|
655 | IGCM_debug_PopStack "IGCM_date_DaysBetweenJulianDate" |
---|
656 | return |
---|
657 | fi |
---|
658 | |
---|
659 | # Break the dates in to year and day portions |
---|
660 | yyyy1=$(( $jul1 / 1000 )) |
---|
661 | yyyy2=$(( $jul2 / 1000 )) |
---|
662 | ddd1=$(( $jul1 % 1000 )) |
---|
663 | ddd2=$(( $jul2 % 1000 )) |
---|
664 | |
---|
665 | # Subtract days |
---|
666 | res=$(( $ddd1 - $ddd2 )) |
---|
667 | |
---|
668 | # Then add days in year until year2 matches year1 |
---|
669 | |
---|
670 | case ${config_UserChoices_CalendarType} in |
---|
671 | 360d|360_day) |
---|
672 | res=$(( ( ( $yyyy1 - $yyyy2 ) * 360 ) + $res )) ;; |
---|
673 | noleap|365_day) |
---|
674 | res=$(( ( ( $yyyy1 - $yyyy2 ) * 365 ) + $res )) ;; |
---|
675 | all_leap|366_day) |
---|
676 | res=$(( ( ( $yyyy1 - $yyyy2 ) * 366 ) + $res )) ;; |
---|
677 | leap|gregorian|standard) |
---|
678 | while [ $yyyy2 -lt $yyyy1 ] |
---|
679 | do |
---|
680 | IGCM_date_DaysInYear $yyyy2 diy |
---|
681 | res=$(( $res + $diy )) |
---|
682 | yyyy2=$(( $yyyy2 + 1 )) |
---|
683 | done |
---|
684 | ;; |
---|
685 | esac |
---|
686 | |
---|
687 | |
---|
688 | # if argument 2 was larger than argument 1 then |
---|
689 | # the arguments were reversed before calculating |
---|
690 | # adjust by reversing the sign |
---|
691 | if [ $1 -lt $2 ] |
---|
692 | then |
---|
693 | res=$(( $res * -1 )) |
---|
694 | fi |
---|
695 | |
---|
696 | # and output the results |
---|
697 | echo $res |
---|
698 | |
---|
699 | IGCM_debug_PopStack "IGCM_date_DaysBetweenJulianDate" |
---|
700 | } |
---|
701 | |
---|
702 | #D-#================================================================== |
---|
703 | #D-function IGCM_date_DaysBetweenGregorianDate () |
---|
704 | #D-* Purpose: Calculate the days difference between two dates and reports |
---|
705 | #D- the number days as grg1 - grg2 |
---|
706 | #D-* Usage: IGCM_date_DaysBetweenGregorianDate grg1 grg2 |
---|
707 | #D- where gregorian date is in the form yyyymmdd |
---|
708 | #D- |
---|
709 | function IGCM_date_DaysBetweenGregorianDate |
---|
710 | { |
---|
711 | IGCM_debug_PushStack "IGCM_date_DaysBetweenGregorianDate" $@ |
---|
712 | |
---|
713 | # calculates the days difference between two dates and reports |
---|
714 | # the number days as grg1 - grg2 |
---|
715 | # usage IGCM_date_DaysBetweenGregorianDate grg1 grg2 |
---|
716 | # where gregorian date is in the form yyyymmdd |
---|
717 | |
---|
718 | usage () { |
---|
719 | echo "Usage:" |
---|
720 | echo " IGCM_date_DaysBetweenGregorianDate grg1 grg2" |
---|
721 | echo "" |
---|
722 | echo " Calculate day difference between" |
---|
723 | echo " two gregorian dates (grg1 - grg2)" |
---|
724 | echo " where a gregorian date is in the form of yyyymmdd." |
---|
725 | } |
---|
726 | |
---|
727 | if [ $# -lt 2 ]; then |
---|
728 | usage |
---|
729 | IGCM_debug_Exit "IGCM_date_DaysBetweenGregorianDate" |
---|
730 | fi |
---|
731 | |
---|
732 | # convert each date to julian |
---|
733 | grg1=$1 |
---|
734 | grg2=$2 |
---|
735 | |
---|
736 | jul1=$( IGCM_date_ConvertGregorianDateToJulian $grg1 ) |
---|
737 | jul2=$( IGCM_date_ConvertGregorianDateToJulian $grg2 ) |
---|
738 | |
---|
739 | if [ $jul1 -ne $jul2 ]; then |
---|
740 | # calculate the answer using IGCM_date_DaysBetweenJulianDate |
---|
741 | res=$( IGCM_date_DaysBetweenJulianDate $jul1 $jul2 ) |
---|
742 | # and output the results |
---|
743 | echo $res |
---|
744 | else |
---|
745 | echo 0 |
---|
746 | fi |
---|
747 | |
---|
748 | IGCM_debug_PopStack "IGCM_date_DaysBetweenGregorianDate" |
---|
749 | } |
---|
750 | |
---|
751 | #D-#================================================================== |
---|
752 | #D-function IGCM_date_DaysSinceJC () |
---|
753 | #D-* Purpose: Calculate the days difference between a date and 00010101 |
---|
754 | #D-* Usage: IGCM_date_DaysSinceJC grg1 |
---|
755 | #D- where gregorian date is in the form yyyymmdd |
---|
756 | #D- |
---|
757 | function IGCM_date_DaysSinceJC |
---|
758 | { |
---|
759 | IGCM_debug_PushStack "IGCM_date_DaysSinceJC" $@ |
---|
760 | |
---|
761 | # calculates the days difference between a date and 00010101 |
---|
762 | # usage IGCM_date_DaysSinceJC grg1 |
---|
763 | # where gregorian date is in the form yyyymmdd |
---|
764 | |
---|
765 | usage () { |
---|
766 | echo "Usage:" |
---|
767 | echo " IGCM_date_DaysSinceJC grg1" |
---|
768 | echo "" |
---|
769 | echo " Calculate day difference between" |
---|
770 | echo " a gregorian date and 00010101" |
---|
771 | echo " where a gregorian date is in the form of yyyymmdd." |
---|
772 | } |
---|
773 | |
---|
774 | if [ $# -lt 1 ]; then |
---|
775 | usage |
---|
776 | IGCM_debug_Exit "IGCM_date_DaysSinceJC" |
---|
777 | fi |
---|
778 | |
---|
779 | typeset aux num |
---|
780 | |
---|
781 | if [ ${1} -lt 5000000 ]; then |
---|
782 | case ${config_UserChoices_CalendarType} in |
---|
783 | 360d|360_day) |
---|
784 | aux=-360;; |
---|
785 | noleap|365_day) |
---|
786 | aux=-365;; |
---|
787 | all_leap|366_day) |
---|
788 | aux=-366;; |
---|
789 | leap|gregorian|standard) |
---|
790 | aux=-366;; |
---|
791 | esac |
---|
792 | num=101 |
---|
793 | elif [ ${1} -lt 15000000 ]; then |
---|
794 | # To save CPU type we use auxiliary value |
---|
795 | # which is number of days since JC and 10000101 |
---|
796 | case ${config_UserChoices_CalendarType} in |
---|
797 | 360d|360_day) |
---|
798 | aux=359640;; |
---|
799 | noleap|365_day) |
---|
800 | aux=364635;; |
---|
801 | all_leap|366_day) |
---|
802 | aux=365634;; |
---|
803 | leap|gregorian|standard) |
---|
804 | aux=364877;; |
---|
805 | esac |
---|
806 | num=10000101 |
---|
807 | else |
---|
808 | # To save CPU type we use auxiliary value |
---|
809 | # which is number of days since JC and 19000101 |
---|
810 | case ${config_UserChoices_CalendarType} in |
---|
811 | 360d|360_day) |
---|
812 | aux=683640;; |
---|
813 | noleap|365_day) |
---|
814 | aux=693135;; |
---|
815 | all_leap|366_day) |
---|
816 | aux=695034;; |
---|
817 | leap|gregorian|standard) |
---|
818 | aux=693595;; |
---|
819 | esac |
---|
820 | num=19000101 |
---|
821 | fi |
---|
822 | echo $(( $( IGCM_date_DaysBetweenGregorianDate $1 ${num} ) + $aux )) |
---|
823 | |
---|
824 | IGCM_debug_PopStack "IGCM_date_DaysSinceJC" |
---|
825 | } |
---|
826 | |
---|
827 | #D-#================================================================== |
---|
828 | #D-function IGCM_date_Check |
---|
829 | #D- * Purpose: Check the present file by comparison with a reference file |
---|
830 | function IGCM_date_Check |
---|
831 | { |
---|
832 | IGCM_debug_PushStack "IGCM_date_Check" |
---|
833 | |
---|
834 | #--------------------- |
---|
835 | if [ ! -n "${libIGCM}" ] ; then |
---|
836 | echo "Check libIGCM_date ...........................................[ FAILED ]" |
---|
837 | echo "--Error--> libIGCM variable is not defined" |
---|
838 | IGCM_debug_Exit "IGCM_date_Check" |
---|
839 | fi |
---|
840 | |
---|
841 | #--------------------- |
---|
842 | whence -v gawk > /dev/null 2>&1 |
---|
843 | if [ ! $? -eq 0 ] ; then |
---|
844 | echo "Check libIGCM_date ...........................................[ FAILED ]" |
---|
845 | echo "--Error--> gawk command is not defined" |
---|
846 | IGCM_debug_Exit "IGCM_date_Check" |
---|
847 | fi |
---|
848 | |
---|
849 | #--------------------- |
---|
850 | ${libIGCM}/libIGCM_date/IGCM_date_Test.ksh > IGCM_date_Test.ref.failed 2>&1 |
---|
851 | |
---|
852 | if diff IGCM_date_Test.ref.failed ${libIGCM}/libIGCM_date/IGCM_date_Test${dY}.ref > /dev/null 2>&1 ; then |
---|
853 | echo "Check libIGCM_date ...............................................[ OK ]" |
---|
854 | rm -f IGCM_date_Test.ref.failed |
---|
855 | else |
---|
856 | echo "Check libIGCM_date ...........................................[ FAILED ]" |
---|
857 | echo "--Error--> Execution of ${libIGCM}/libIGCM_date/IGCM_date_Test.ksh" |
---|
858 | echo " has produced the file IGCM_date_Test.ref.failed" |
---|
859 | echo " Please analyse differences with the reference file by typing:" |
---|
860 | echo " diff IGCM_date_Test.ref.failed ${libIGCM}/libIGCM_date/IGCM_date_Test${dY}.ref" |
---|
861 | echo " Report errors to the author: Sebastien.Denvil@ipsl.jussieu.fr" |
---|
862 | IGCM_debug_Exit "IGCM_date_Check" |
---|
863 | fi |
---|
864 | |
---|
865 | #--------------------- |
---|
866 | IGCM_debug_PopStack "IGCM_date_Check" |
---|
867 | } |
---|
868 | |
---|
869 | #================================================================== |
---|