source: CONFIG_DEVT/IPSLCM6.5_work_ENSEMBLES/libIGCM/libIGCM_date/libIGCM_date.ksh @ 5899

Last change on this file since 5899 was 5899, checked in by aclsce, 3 years ago

Modified libIGCM and configuration to run XIOS ensembles.

File size: 30.0 KB
Line 
1#!/bin/ksh
2
3#**************************************************************
4# Author: Sebastien Denvil
5# Contact: Sebastien.Denvil__at__ipsl.jussieu.fr
6# $Revision:: 1206                                     $ Revision of last commit
7# $Author:: sdipsl                                     $ Author of last commit
8# $Date:: 2015-06-05 17:28:35 +0200 (Fri, 05 Jun 2015) $ 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
36typeset -r dY=${dY:=4}
37#typeset -r MaxpY=$( echo "10^"$((dY+1)) | bc -l )
38# Number of digit in non-human date representation
39typeset -r pY=$(( dY+4 ))
40
41#==================================================================
42function IGCM_date_YearDigit
43{
44  IGCM_debug_PushStack "IGCM_date_YearDigit" $@
45
46  typeset NUM
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#==================================================================
55function IGCM_date_GregorianDigit
56{
57  IGCM_debug_PushStack "IGCM_date_GregorianDigit" $@
58
59  typeset NUM
60
61  NUM=$(( 10#${1} ))
62
63  echo $( gawk "BEGIN { printf \"%0${pY}d\",${NUM} }" )
64
65  IGCM_debug_PopStack "IGCM_date_GregorianDigit"
66}
67
68#==================================================================
69function IGCM_date_HumanDigit
70{
71  IGCM_debug_PushStack "IGCM_date_HumanDigit" $@
72
73  echo $( IGCM_date_GregorianDigit $( print ${1} | sed 's/-//g' ) ) \
74    | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1-\2-\3/"
75
76  IGCM_debug_PopStack "IGCM_date_HumanDigit"
77}
78
79#==================================================================
80function IGCM_date_SupressZeros
81{
82  IGCM_debug_PushStack "IGCM_date_SupressZeros" $@
83  echo $( print ${1} | sed -e "s/0*//" )
84  IGCM_debug_PopStack "IGCM_date_SupressZeros"
85}
86
87#==================================================================
88function IGCM_date_ConvertFormatToGregorian
89{
90  IGCM_debug_PushStack "IGCM_date_ConvertFormatToGregorian" $@
91
92  # from a yyyy-mm-dd date format return
93  # a yyymmdd date format
94  # usage IGCM_date_ConvertFormat yyyy-mm-dd
95
96  # if there is no argument on the command line,
97  # then assume that a y-m-d formated date is being
98  # piped in
99  typeset ymd
100  if [ $# = 0 ]
101  then
102    read ymd
103  else
104    ymd=$1
105  fi
106
107  IGCM_date_GregorianDigit $( print ${ymd} | sed 's/-//g' )
108
109  IGCM_debug_PopStack "IGCM_date_ConvertFormatToGregorian"
110}
111
112#==================================================================
113function IGCM_date_ConvertFormatToHuman
114{
115  IGCM_debug_PushStack "IGCM_date_ConvertFormatToHuman" $@
116
117  # from a yyyymmdd date format return
118  # a yyyy-mm-dd date format
119  # usage IGCM_date_ConvertFormat yyyymmdd
120
121  # if there is no argument on the command line,
122  # then assume that a yyyymmdd formated date is being
123  # piped in
124  typeset dt
125  if [ $# = 0 ]
126  then
127    read dt
128  else
129    dt=$1
130  fi
131
132  # break the yyyymmdd into separate parts for year, month and day
133  echo $( IGCM_date_GregorianDigit ${dt} ) | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1-\2-\3/"
134
135  IGCM_debug_PopStack "IGCM_date_ConvertFormatToHuman"
136}
137
138#==================================================================
139function IGCM_date_GetYearMonth
140{
141  IGCM_debug_PushStack "IGCM_date_GetYearMonth" $@
142
143  # from a yyyymmdd date format return
144  # a yyyy year and mm month
145  # usage IGCM_date_GetYearMonth yyyymmdd year_var month_var
146
147  # if there is no argument on the command line,
148  # then assume that a yyyymmdd formated date is being
149  # piped in
150  typeset dt
151  if [ $# = 0 ]
152  then
153    read dt
154  else
155    dt=$1
156  fi
157
158  # break the yyyymmdd into separate parts for year, month and day
159  eval $2=$( IGCM_date_GregorianDigit ${dt} | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1/" )
160  eval $3=$( IGCM_date_GregorianDigit ${dt} | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\2/" )
161
162  IGCM_debug_PopStack "IGCM_date_GetYearMonth"
163}
164
165#==================================================================
166function IGCM_date_GetYearMonthDay
167{
168  IGCM_debug_PushStack "IGCM_date_GetYearMonthDay" $@
169
170  # from a yyyymmdd date format return
171  # a yyyy year, mm month and dd day
172  # usage IGCM_date_GetYearMonthDay yyyymmdd year_var month_var day_var
173
174  # if there is no argument on the command line,
175  # then assume that a yyyymmdd formated date is being
176  # piped in
177  typeset dt
178  if [ $# = 0 ]
179  then
180    read dt
181  else
182    dt=$1
183  fi
184
185  # break the yyyymmdd into separate parts for year, month and day
186  eval $2=$( IGCM_date_GregorianDigit ${dt} | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1/" )
187  eval $3=$( IGCM_date_GregorianDigit ${dt} | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\2/" )
188  eval $4=$( IGCM_date_GregorianDigit ${dt} | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\3/" )
189
190  IGCM_debug_PopStack "IGCM_date_GetYearMonthDay"
191}
192
193#D-#==================================================================
194#D-function IGCM_date_DaysInYear
195#D-* Purpose: Return the number of days in a year
196#D-* Usage: IGCM_date_DaysInYear yyyy
197#D-         if there is no argument on the command line,
198#D-         then assume that a yyyy is being piped in
199#D-
200function IGCM_date_DaysInYear
201{
202#    IGCM_debug_PushStack "IGCM_date_DaysInYear" $@
203  # return the number of days in a year
204  # usage IGCM_date_DaysInYear yyyy
205
206  # What is the calendar :
207  case ${config_UserChoices_CalendarType} in
208  360d|360_day)
209    if [ X$2 = X ] ; then
210      echo 360
211    else
212      eval $2=360 > /dev/null 2>&1
213    fi
214#    IGCM_debug_PopStack "IGCM_date_DaysInYear"
215    return;;
216  noleap|365_day)
217    if [ X$2 = X ] ; then
218      echo 365
219    else
220      eval $2=365 > /dev/null 2>&1
221    fi
222
223#    IGCM_debug_PopStack "IGCM_date_DaysInYear"
224    return;;
225  all_leap|366_day)
226    if [ X$2 = X ] ; then
227      echo 366
228    else
229      eval $2=366 > /dev/null 2>&1
230    fi
231
232#    IGCM_debug_PopStack "IGCM_date_DaysInYear"
233    return;;
234  esac
235
236  typeset y a
237
238  # if there is no argument on the command line,
239  # then assume that a yyyy is being piped in
240  if [ $# = 0 ]
241  then
242    read y
243  else
244    y=$(( 10#${1} ))
245  fi
246
247  # a year is a leap year if it is even divisible by 4
248  # but not evenly divisible by 100
249  # unless it is evenly divisible by 400
250
251  # if it is evenly divisible by 400 it must be a leap year
252  a=$(( $y % 400 ))
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  # if it is evenly divisible by 100 it must not be a leap year
266  a=$(( $y % 100 ))
267  if [ $a = 0 ]
268  then
269    if [ X$2 = X ] ; then
270      echo 365
271    else
272      eval $2=365 > /dev/null 2>&1
273    fi
274
275#    IGCM_debug_PopStack "IGCM_date_DaysInYear"
276    return
277  fi
278
279  # if it is evenly divisible by 4 it must be a leap year
280  a=$(( $y % 4 ))
281  if [ $a = 0 ]
282  then
283    if [ X$2 = X ] ; then
284      echo 366
285    else
286      eval $2=366 > /dev/null 2>&1
287    fi
288
289#    IGCM_debug_PopStack "IGCM_date_DaysInYear"
290    return
291  fi
292
293  # otherwise it is not a leap year
294  if [ X$2 = X ] ; then
295    echo 365
296  else
297    eval $2=365 > /dev/null 2>&1
298  fi
299
300#    IGCM_debug_PopStack "IGCM_date_DaysInYear"
301}
302
303#D-#==================================================================
304#D-function IGCM_date_DaysInMonth
305#D-* Purpose: Calculate the number of days in a month
306#D-* Usage: IGCM_date_DaysInMonth yyyy mm
307#D-         or IGCM_date_DaysInMonth yyyymmdd
308#D-         if there are no command line arguments then
309#D-         assume that a yyyymmdd is being piped in and read the value.
310#D-         if there is only one argument assume it is a yyyymmdd on the command line
311#D-         other wise it is a yyyy and mm on the command line
312function IGCM_date_DaysInMonth
313{
314#    IGCM_debug_PushStack "IGCM_date_DaysInMonth" $@
315
316  # calculates the number of days in a month
317  # usage IGCM_date_DaysInMonth yyyy mm
318  # or IGCM_date_DaysInMonth yyyymmdd
319
320  # What is the calendar :
321  if ( [ "${config_UserChoices_CalendarType}" = "360d" ] || [ "${config_UserChoices_CalendarType}" = "360_day" ] ) ; then
322    if [ X$3 = X ] ; then
323      echo 30
324    else
325      eval $3=30 > /dev/null 2>&1
326    fi
327
328#   IGCM_debug_PopStack "IGCM_date_DaysInMonth"
329    return
330  fi
331
332  typeset ymd y m
333
334  # if there are no command line arguments then assume that a yyyymmdd is being
335  # piped in and read the value.
336  # if there is only one argument assume it is a yyyymmdd on the command line
337  # other wise it is a yyyy and mm on the command line
338  if [ $# = 0 ]
339  then
340    read ymd
341  elif [ $# = 1 ]
342  then
343    ymd=$1
344  else
345    ymd=$(( ( $1 * 10000 ) + ( $2 * 100 ) + 1 ))
346  fi
347
348  # extract the year and the month
349  y=$(( $ymd / 10000 )) ;
350  m=$(( ( $ymd % 10000 ) / 100 )) ;
351
352  # 30 days hath september etc.
353  case $m in
354  1|3|5|7|8|10|12)
355    if [ X$3 = X ] ; then
356      echo 31
357    else
358      eval $3=31 > /dev/null 2>&1
359    fi
360
361#           IGCM_debug_PopStack "IGCM_date_DaysInMonth"
362    return ;;
363  4|6|9|11)
364    if [ X$3 = X ] ; then
365      echo 30
366    else
367      eval $3=30 > /dev/null 2>&1
368    fi
369
370#           IGCM_debug_PopStack "IGCM_date_DaysInMonth"
371    return ;;
372  *) ;;
373  esac
374
375  # except for month 2 which depends on whether the year is a leap year
376  # Use IGCM_date_DaysInYear to get the number of days in the year and return a value
377  # accordingly.
378
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-
411function 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-
461function 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-
514function 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-
584function 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-
619function 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  typeset jul1 jul2 yyyy1 yyyy2 ddd1 ddd2 res
643
644  # This process subtracts arg2 from arg1. If arg2 is larger
645  # then reverse the arguments. The calculations are done, and
646  # then the sign is reversed
647  if [ $1 -lt $2 ]
648  then
649    jul1=$2
650    jul2=$1
651  elif [ $1 -gt $2 ]
652  then
653    jul1=$1
654    jul2=$2
655  else
656    echo 0
657    IGCM_debug_PopStack "IGCM_date_DaysBetweenJulianDate"
658    return
659  fi
660
661  # Break the dates in to year and day portions
662  yyyy1=$(( $jul1 / 1000 ))
663  yyyy2=$(( $jul2 / 1000 ))
664  ddd1=$(( $jul1 % 1000 ))
665  ddd2=$(( $jul2 % 1000 ))
666
667  # Subtract days
668  res=$(( $ddd1 - $ddd2 ))
669
670  # Then add days in year until year2 matches year1
671  case ${config_UserChoices_CalendarType} in
672  360d|360_day)
673    res=$(( ( ( $yyyy1 - $yyyy2 ) * 360 ) + $res )) ;;
674  noleap|365_day)
675    res=$(( ( ( $yyyy1 - $yyyy2 ) * 365 ) + $res )) ;;
676  all_leap|366_day)
677    res=$(( ( ( $yyyy1 - $yyyy2 ) * 366 ) + $res )) ;;
678  leap|gregorian|standard)
679    while [ $yyyy2 -lt $yyyy1 ]
680    do
681      IGCM_date_DaysInYear $yyyy2 diy
682      res=$(( $res + $diy ))
683      yyyy2=$(( $yyyy2 + 1 ))
684    done
685    ;;
686  esac
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-
709function 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  typeset grg1 grg2 jul1 jul2 res
733
734  # convert each date to julian
735  grg1=$1
736  grg2=$2
737
738  jul1=$( IGCM_date_ConvertGregorianDateToJulian $grg1 )
739  jul2=$( IGCM_date_ConvertGregorianDateToJulian $grg2 )
740
741  if [ $jul1 -ne $jul2 ]; then
742    # calculate the answer using IGCM_date_DaysBetweenJulianDate
743    res=$( IGCM_date_DaysBetweenJulianDate $jul1 $jul2 )
744    # and output the results
745    echo $res
746  else
747    echo 0
748  fi
749
750  IGCM_debug_PopStack "IGCM_date_DaysBetweenGregorianDate"
751}
752
753#D-#==================================================================
754#D-function IGCM_date_DaysSinceJC ()
755#D-* Purpose: Calculate the days difference between a date and 00010101
756#D-* Usage: IGCM_date_DaysSinceJC grg1
757#D-         where gregorian date is in the form yyyymmdd
758#D-
759function IGCM_date_DaysSinceJC
760{
761  IGCM_debug_PushStack "IGCM_date_DaysSinceJC" $@
762
763  # calculates the days difference between a date and 00010101
764  # usage IGCM_date_DaysSinceJC grg1
765  # where gregorian date is in the form yyyymmdd
766
767  usage () {
768    echo "Usage:"
769    echo " IGCM_date_DaysSinceJC grg1"
770    echo ""
771    echo " Calculate day difference between"
772    echo " a gregorian date and 00010101"
773    echo " where a gregorian date is in the form of yyyymmdd."
774  }
775
776  if [ $# -lt 1 ]; then
777    usage
778    IGCM_debug_Exit "IGCM_date_DaysSinceJC"
779  fi
780
781  typeset aux num
782
783  if   [ ${1} -lt  5000000 ]; then
784    case ${config_UserChoices_CalendarType} in
785    360d|360_day)
786      aux=-360;;
787    noleap|365_day)
788      aux=-365;;
789    all_leap|366_day)
790      aux=-366;;
791    leap|gregorian|standard)
792      aux=-366;;
793    esac
794    num=101
795  elif [ ${1} -lt 15000000 ]; then
796    # To save CPU type we use auxiliary value
797    # which is number of days since JC and 10000101
798    case ${config_UserChoices_CalendarType} in
799    360d|360_day)
800      aux=359640;;
801    noleap|365_day)
802      aux=364635;;
803    all_leap|366_day)
804      aux=365634;;
805    leap|gregorian|standard)
806      aux=364877;;
807    esac
808    num=10000101
809  else
810    # To save CPU type we use auxiliary value
811    # which is number of days since JC and 19000101
812    case ${config_UserChoices_CalendarType} in
813    360d|360_day)
814      aux=683640;;
815    noleap|365_day)
816      aux=693135;;
817    all_leap|366_day)
818      aux=695034;;
819    leap|gregorian|standard)
820      aux=693595;;
821    esac
822    num=19000101
823  fi
824  echo $(( $( IGCM_date_DaysBetweenGregorianDate $1 ${num} ) + $aux ))
825
826  IGCM_debug_PopStack "IGCM_date_DaysSinceJC"
827}
828
829#D-#==================================================================
830#D-function IGCM_date_DaysInPreviousPeriod ()
831#D-* Purpose: Give the numbers of days during the previous prd1 period from grg1 date # OLD create_ts_begin_date
832#D-* Usage: IGCM_date_DaysInPreviousPeriod grg1 prd1 [end]
833#D-         where grg1 gregorian date is in the form yyyymmdd
834#D-         where prd1 period is in the form N[Yy], N[Mm], N[Dd]. N integer
835#D-         where [end] is an optionnal keyword to specify grg1 is the end of prd1
836#D-
837function IGCM_date_DaysInPreviousPeriod {
838  IGCM_debug_PushStack "IGCM_date_DaysInPreviousPeriod" $@
839
840  typeset Length Period treatedYear PeriodLengthInYears PeriodLengthInMonths year0 i
841
842  Period=${2}
843  case ${Period} in
844  *Y|*y)
845    PeriodLengthInYears=$( echo ${Period} | awk -F '[yY]' '{print $1}' )
846    IGCM_date_GetYearMonth ${1} year month
847    year=$( IGCM_date_SupressZeros ${year} )
848    if [ X${3} = Xend ] ; then
849      (( year = year - PeriodLengthInYears + 1))
850    fi
851    Length=0
852    i=0
853    until [ $i -ge $PeriodLengthInYears ] ; do
854      (( Length = Length + $( IGCM_date_DaysInYear $(( year + i )) ) ))
855      (( i = i + 1 ))
856    done
857    ;;
858  *M|*m)
859    PeriodLengthInMonths=$( echo ${Period} | awk -F '[mM]' '{print $1}' )
860    IGCM_date_GetYearMonth ${1} year month
861    year=$( IGCM_date_SupressZeros ${year} )
862    if [ X${3} = Xend ] ; then
863      (( month = month - PeriodLengthInMonths + 1 ))
864    fi
865    year0=year
866    if [ $month -le 0 ] ; then
867      (( month = month + 12 ))
868      year=$( printf "%04i\n" $(( year - 1 )) )
869    fi
870    month=$( printf "%02i\n" ${month} )
871    treatedYear=0
872    Length=0
873    i=0
874    for ((i = 0; i < ${PeriodLengthInMonths}; i += 1)) ; do
875
876      (( Length = Length + $( IGCM_date_DaysInMonth $year $(( month + i - 12 * treatedYear )) ) ))
877
878      if [ $(( month + i )) -ge $(( 12 * (treatedYear + 1) )) ] ; then
879        (( year = year0 + 1 ))
880        (( treatedYear = treatedYear + 1 ))
881      fi
882    done
883    ;;
884  *D|*d)
885    Length=$( echo ${Period} | sed -e "s/[dD]//" ) ;;
886  *)
887    IGCM_debug_Exit "IGCM_date_DaysInPreviousPeriod " ${Period} " invalid PeriodLength : choose in *Y, *M, *D."
888    IGCM_debug_Verif_Exit ;;
889  esac
890  echo ${Length}
891
892  IGCM_debug_PopStack "IGCM_date_DaysInPreviousPeriod"
893}
894
895#D-#==================================================================
896#D-function IGCM_date_DaysInNextPeriod ()
897#D-* Purpose: Give the numbers of days during the next prd1 period from grg1 date # OLD create_ts_next_date
898#D-* Usage: IGCM_date_DaysInNextPeriod grg1 prd1
899#D-         where grg1 gregorian date is in the form yyyymmdd
900#D-         where prd1 period is in the form N[Yy], N[Mm], N[Dd]. N integer
901#D-
902function IGCM_date_DaysInNextPeriod {
903  IGCM_debug_PushStack "IGCM_date_DaysInNextPeriod" $@
904
905  typeset Length Period treatedYear PeriodLengthInYears PeriodLengthInMonths year0 month0 i
906
907  Period=${2}
908  case ${Period} in
909  *Y|*y)
910    PeriodLengthInYears=$( echo ${Period} | awk -F '[yY]' '{print $1}' )
911    IGCM_date_GetYearMonth ${1} year month
912    year=$( IGCM_date_SupressZeros ${year} )
913    Length=0
914    i=0
915    until [ $i -ge $PeriodLengthInYears ] ; do
916      (( Length = Length + $( IGCM_date_DaysInYear $(( year + i + 1 )) ) ))
917      (( i = i + 1 ))
918    done
919    ;;
920  *M|*m)
921    PeriodLengthInMonths=$( echo ${Period} | awk -F '[mM]' '{print $1}' )
922    IGCM_date_GetYearMonth ${1} year month
923    year=$( IGCM_date_SupressZeros ${year} )
924    year0=year
925    if [ $(( month + 1 )) -lt 13 ] ; then
926      month0=$(( month + 1 ))
927    else
928      month0=$(( month + 1 - 12 ))
929      (( year = year0 + 1 ))
930    fi
931    treatedYear=0
932    Length=0
933    i=0
934    for ((i = 0; i < ${PeriodLengthInMonths}; i += 1)) ; do
935
936      (( Length = Length + $( IGCM_date_DaysInMonth $year $(( month0 + i - 12 * treatedYear )) ) ))
937
938      if [ $(( month0 + i )) -ge $(( 12 * (treatedYear + 1) )) ] ; then
939        (( year = year0 + 1 ))
940        (( treatedYear = treatedYear + 1 ))
941      fi
942    done
943    ;;
944  *D|*d)
945    Length=$( echo ${Period} | sed -e "s/[dD]//" ) ;;
946  *)
947    IGCM_debug_Exit "IGCM_date_DaysInNextPeriod " ${Period} " invalid PeriodLength : choose in *Y, *M, *D."
948    IGCM_debug_Verif_Exit ;;
949  esac
950  echo ${Length}
951
952  IGCM_debug_PopStack "IGCM_date_DaysInNextPeriod"
953}
954
955#D-#==================================================================
956#D-function IGCM_date_DaysInCurrentPeriod ()
957#D-* Purpose: Give the numbers of days during the Current prd1 period from grg1 date
958#D-* Usage: IGCM_date_DaysInCurrentPeriod grg1 prd1
959#D-         where grg1 gregorian date is in the form yyyymmdd
960#D-         where prd1 period is in the form N[Yy], N[Mm], N[Dd]. N integer
961#D-
962function IGCM_date_DaysInCurrentPeriod {
963  IGCM_debug_PushStack "IGCM_date_DaysInCurrentPeriod" $@
964
965  typeset Length Period treatedYear PeriodLengthInYears PeriodLengthInMonths year0 i
966
967  Period=${2}
968  case ${Period} in
969  *Y|*y)
970    PeriodLengthInYears=$( echo ${Period} | awk -F '[yY]' '{print $1}' )
971    IGCM_date_GetYearMonth ${1} year month
972    year=$( IGCM_date_SupressZeros ${year} )
973    month=$( IGCM_date_SupressZeros ${month} )
974    Length=0
975    # if starting after february and using leap calendar
976    # we need to add the number of days of the next year (potentially a leap year)
977    if [ ${month} -gt 2 ] ; then
978      (( year = year + 1 ))
979    fi
980    i=0
981    until [ $i -ge $PeriodLengthInYears ] ; do
982      (( Length = Length + $( IGCM_date_DaysInYear $(( year + i )) ) ))
983      (( i = i + 1 ))
984    done
985    ;;
986  *M|*m)
987    PeriodLengthInMonths=$( echo ${Period} | awk -F '[mM]' '{print $1}' )
988    IGCM_date_GetYearMonth ${1} year month
989    year=$( IGCM_date_SupressZeros ${year} )
990    year0=year
991    treatedYear=0
992    Length=0
993    i=0
994    for ((i = 0; i < ${PeriodLengthInMonths}; i += 1)) ; do
995
996      (( Length = Length + $( IGCM_date_DaysInMonth $year $(( month + i - 12 * treatedYear )) ) ))
997
998      if [ $(( month + i )) -ge $(( 12 * (treatedYear + 1) )) ] ; then
999        (( year = year0 + 1 ))
1000        (( treatedYear = treatedYear + 1 ))
1001      fi
1002    done
1003    ;;
1004  *D|*d)
1005    Length=$( echo ${Period} | sed -e "s/[dD]//" ) ;;
1006  *)
1007    IGCM_debug_Exit "IGCM_date_DaysInCurrentPeriod " ${Period} " invalid PeriodLength : choose in *Y, *M, *D."
1008    IGCM_debug_Verif_Exit ;;
1009  esac
1010  echo ${Length}
1011
1012  IGCM_debug_PopStack "IGCM_date_DaysInCurrentPeriod"
1013}
1014
1015#D-#==================================================================
1016#D-function IGCM_date_Check
1017#D- * Purpose: Check the present file by comparison with a reference file
1018function IGCM_date_Check
1019{
1020  #---------------------
1021  if [ ! -n "${libIGCM}" ] ; then
1022    echo "Check libIGCM_date ...........................................[ FAILED ]"
1023    echo "--Error--> libIGCM variable is not defined"
1024    IGCM_debug_Exit "IGCM_date_Check"
1025  fi
1026
1027  #---------------------
1028  whence -v gawk > /dev/null 2>&1
1029  if [ ! $? -eq 0 ] ; then
1030    echo "Check libIGCM_date ...........................................[ FAILED ]"
1031    echo "--Error--> gawk command is not defined"
1032    IGCM_debug_Exit "IGCM_date_Check"
1033  fi
1034
1035  #---------------------
1036  # No need to remove timestamps here
1037  diff ${libIGCM}/libIGCM_date/IGCM_date_Test${dY}.ref <(${libIGCM}/libIGCM_date/IGCM_date_Test.ksh) > /dev/null 2>&1
1038  status=$?
1039
1040  if [ ${status} -eq 0 ] ; then
1041    echo "Check libIGCM_date ...............................................[ OK ]"
1042  else
1043    echo "Check libIGCM_date ...........................................[ FAILED ]"
1044    echo "--Error--> Execution of ${libIGCM}/libIGCM_date/IGCM_date_Test.ksh"
1045    echo "           has produced the file IGCM_date_Test.ref.failed"
1046    echo "           Please analyse differences with the reference file by typing:"
1047    echo "           diff IGCM_date_Test.ref.failed ${libIGCM}/libIGCM_date/IGCM_date_Test${dY}.ref"
1048    echo "           Report errors to the author: Sebastien.Denvil@ipsl.jussieu.fr"
1049    diff ${libIGCM}/libIGCM_date/IGCM_date_Test${dY}.ref <(${libIGCM}/libIGCM_date/IGCM_date_Test.ksh)
1050    IGCM_debug_Exit "IGCM_date_Check"
1051  fi
1052}
Note: See TracBrowser for help on using the repository browser.