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