source: trunk/libIGCM/libIGCM_date/libIGCM_date.ksh @ 732

Last change on this file since 732 was 732, checked in by sdipsl, 12 years ago
  • strange behaviour when reducing the scope of year and month variable within IGCM_date_DaysIn*Period

==> the function IGCM_date_GetYearMonth then behave strangely.

  • Property licence set to
    The following licence information concerns ONLY the libIGCM tools
    ==================================================================

    Copyright © Centre National de la Recherche Scientifique CNRS
    Commissariat à l'Énergie Atomique CEA

    libIGCM : Library for Portable Models Computation of IGCM Group.

    IGCM Group is the french IPSL Global Climate Model Group.

    This library is a set of shell scripts and functions whose purpose is
    the management of the initialization, the launch, the transfer of
    output files, the post-processing and the monitoring of datas produce
    by any numerical program on any plateforme.

    This software is governed by the CeCILL license under French law and
    abiding by the rules of distribution of free software. You can use,
    modify and/ or redistribute the software under the terms of the CeCILL
    license as circulated by CEA, CNRS and INRIA at the following URL
    "http://www.cecill.info".

    As a counterpart to the access to the source code and rights to copy,
    modify and redistribute granted by the license, users are provided only
    with a limited warranty and the software's author, the holder of the
    economic rights, and the successive licensors have only limited
    liability.

    In this respect, the user's attention is drawn to the risks associated
    with loading, using, modifying and/or developing or reproducing the
    software by the user in light of its specific status of free software,
    that may mean that it is complicated to manipulate, and that also
    therefore means that it is reserved for developers and experienced
    professionals having in-depth computer knowledge. Users are therefore
    encouraged to load and test the software's suitability as regards their
    requirements in conditions enabling the security of their systems and/or
    data to be ensured and, more generally, to use and operate it in the
    same conditions as regards security.

    The fact that you are presently reading this means that you have had
    knowledge of the CeCILL license and that you accept its terms.
  • Property svn:keywords set to Revision Author Date
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::                                          $ 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
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  echo $( gawk "BEGIN { printf \"%0${pY}d\",${NUM} }" )
63
64  IGCM_debug_PopStack "IGCM_date_GregorianDigit"
65}
66
67#==================================================================
68function IGCM_date_HumanDigit
69{
70  IGCM_debug_PushStack "IGCM_date_HumanDigit" $@
71
72  echo $( IGCM_date_GregorianDigit $( print ${1} | sed 's/-//g' ) ) \
73    | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1-\2-\3/"
74
75  IGCM_debug_PopStack "IGCM_date_HumanDigit"
76}
77
78#==================================================================
79function IGCM_date_SupressZeros
80{
81  IGCM_debug_PushStack "IGCM_date_SupressZeros" $@
82  echo $( print ${1} | sed -e "s/0*//" )
83  IGCM_debug_PopStack "IGCM_date_SupressZeros"
84}
85
86#==================================================================
87function IGCM_date_ConvertFormatToGregorian
88{
89  IGCM_debug_PushStack "IGCM_date_ConvertFormatToGregorian" $@
90
91  # from a yyyy-mm-dd date format return
92  # a yyymmdd date format
93  # usage IGCM_date_ConvertFormat yyyy-mm-dd
94
95  # if there is no argument on the command line,
96  # then assume that a y-m-d formated date is being
97  # piped in
98  typeset ymd
99  if [ $# = 0 ]
100  then
101    read ymd
102  else
103    ymd=$1
104  fi
105
106  IGCM_date_GregorianDigit $( print ${ymd} | sed 's/-//g' )
107
108  IGCM_debug_PopStack "IGCM_date_ConvertFormatToGregorian"
109}
110
111#==================================================================
112function IGCM_date_ConvertFormatToHuman
113{
114  IGCM_debug_PushStack "IGCM_date_ConvertFormatToHuman" $@
115
116  # from a yyyymmdd date format return
117  # a yyyy-mm-dd date format
118  # usage IGCM_date_ConvertFormat yyyymmdd
119
120  # if there is no argument on the command line,
121  # then assume that a yyyymmdd formated date is being
122  # piped in
123  typeset dt
124  if [ $# = 0 ]
125  then
126    read dt
127  else
128    dt=$1
129  fi
130
131  # break the yyyymmdd into separate parts for year, month and day
132  echo $( IGCM_date_GregorianDigit ${dt} ) \
133    | 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=$( echo $( IGCM_date_GregorianDigit ${dt} ) \
160    | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1/" )
161  eval $3=$( echo $( IGCM_date_GregorianDigit ${dt} ) \
162    | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\2/" )
163
164  IGCM_debug_PopStack "IGCM_date_GetYearMonth"
165}
166
167#==================================================================
168function IGCM_date_GetYearMonthDay
169{
170  IGCM_debug_PushStack "IGCM_date_GetYearMonthDay" $@
171
172  # from a yyyymmdd date format return
173  # a yyyy year, mm month and dd day
174  # usage IGCM_date_GetYearMonthDay yyyymmdd year_var month_var day_var
175
176  # if there is no argument on the command line,
177  # then assume that a yyyymmdd formated date is being
178  # piped in
179  typeset dt
180  if [ $# = 0 ]
181  then
182    read dt
183  else
184    dt=$1
185  fi
186
187  # break the yyyymmdd into separate parts for year, month and day
188  eval $2=$( echo $( IGCM_date_GregorianDigit ${dt} ) \
189    | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1/" )
190  eval $3=$( echo $( IGCM_date_GregorianDigit ${dt} ) \
191    | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\2/" )
192  eval $4=$( echo $( IGCM_date_GregorianDigit ${dt} ) \
193    | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\3/" )
194
195  IGCM_debug_PopStack "IGCM_date_GetYearMonthDay"
196}
197
198#D-#==================================================================
199#D-function IGCM_date_DaysInYear
200#D-* Purpose: Return the number of days in a year
201#D-* Usage: IGCM_date_DaysInYear yyyy
202#D-         if there is no argument on the command line,
203#D-         then assume that a yyyy is being piped in
204#D-
205function IGCM_date_DaysInYear
206{
207#    IGCM_debug_PushStack "IGCM_date_DaysInYear" $@
208  # return the number of days in a year
209  # usage IGCM_date_DaysInYear yyyy
210
211  # What is the calendar :
212  case ${config_UserChoices_CalendarType} in
213  360d|360_day)
214    if [ X$2 = X ] ; then
215      echo 360
216    else
217      eval $2=360 > /dev/null 2>&1
218    fi
219#       IGCM_debug_PopStack "IGCM_date_DaysInYear"
220    return;;
221  noleap|365_day)
222    if [ X$2 = X ] ; then
223      echo 365
224    else
225      eval $2=365 > /dev/null 2>&1
226    fi
227
228#       IGCM_debug_PopStack "IGCM_date_DaysInYear"
229    return;;
230  all_leap|366_day)
231    if [ X$2 = X ] ; then
232      echo 366
233    else
234      eval $2=366 > /dev/null 2>&1
235    fi
236
237#       IGCM_debug_PopStack "IGCM_date_DaysInYear"
238    return;;
239  esac
240
241  typeset y a
242
243  # if there is no argument on the command line,
244  # then assume that a yyyy is being piped in
245  if [ $# = 0 ]
246  then
247    read y
248  else
249    y=$(( 10#${1} ))
250  fi
251
252  # a year is a leap year if it is even divisible by 4
253  # but not evenly divisible by 100
254  # unless it is evenly divisible by 400
255
256  # if it is evenly divisible by 400 it must be a leap year
257  a=$(( $y % 400 ))
258  if [ $a = 0 ]
259  then
260    if [ X$2 = X ] ; then
261      echo 366
262    else
263      eval $2=366 > /dev/null 2>&1
264    fi
265
266#       IGCM_debug_PopStack "IGCM_date_DaysInYear"
267    return
268  fi
269
270  # if it is evenly divisible by 100 it must not be a leap year
271  a=$(( $y % 100 ))
272  if [ $a = 0 ]
273  then
274    if [ X$2 = X ] ; then
275      echo 365
276    else
277      eval $2=365 > /dev/null 2>&1
278    fi
279
280#       IGCM_debug_PopStack "IGCM_date_DaysInYear"
281    return
282  fi
283
284  # if it is evenly divisible by 4 it must be a leap year
285  a=$(( $y % 4 ))
286  if [ $a = 0 ]
287  then
288    if [ X$2 = X ] ; then
289      echo 366
290    else
291      eval $2=366 > /dev/null 2>&1
292    fi
293
294#       IGCM_debug_PopStack "IGCM_date_DaysInYear"
295    return
296  fi
297
298  # otherwise it is not a leap year
299  if [ X$2 = X ] ; then
300    echo 365
301  else
302    eval $2=365 > /dev/null 2>&1
303  fi
304
305#    IGCM_debug_PopStack "IGCM_date_DaysInYear"
306}
307
308#D-#==================================================================
309#D-function IGCM_date_DaysInMonth
310#D-* Purpose: Calculate the number of days in a month
311#D-* Usage: IGCM_date_DaysInMonth yyyy mm
312#D-         or IGCM_date_DaysInMonth yyyymmdd
313#D-         if there are no command line arguments then
314#D-         assume that a yyyymmdd is being piped in and read the value.
315#D-         if there is only one argument assume it is a yyyymmdd on the command line
316#D-         other wise it is a yyyy and mm on the command line
317function IGCM_date_DaysInMonth
318{
319#    IGCM_debug_PushStack "IGCM_date_DaysInMonth" $@
320
321  # calculates the number of days in a month
322  # usage IGCM_date_DaysInMonth yyyy mm
323  # or IGCM_date_DaysInMonth yyyymmdd
324
325  # What is the calendar :
326  if ( [ "${config_UserChoices_CalendarType}" = "360d" ] || [ "${config_UserChoices_CalendarType}" = "360_day" ] ) ; then
327    if [ X$3 = X ] ; then
328      echo 30
329    else
330      eval $3=30 > /dev/null 2>&1
331    fi
332
333#   IGCM_debug_PopStack "IGCM_date_DaysInMonth"
334    return
335  fi
336
337  typeset ymd y m
338
339  # if there are no command line arguments then assume that a yyyymmdd is being
340  # piped in and read the value.
341  # if there is only one argument assume it is a yyyymmdd on the command line
342  # other wise it is a yyyy and mm on the command line
343  if [ $# = 0 ]
344  then
345    read ymd
346  elif [ $# = 1 ]
347  then
348    ymd=$1
349  else
350    ymd=$(( ( $1 * 10000 ) + ( $2 * 100 ) + 1 ))
351  fi
352
353  # extract the year and the month
354  y=$(( $ymd / 10000 )) ;
355  m=$(( ( $ymd % 10000 ) / 100 )) ;
356
357  # 30 days hath september etc.
358  case $m in
359  1|3|5|7|8|10|12)
360    if [ X$3 = X ] ; then
361      echo 31
362    else
363      eval $3=31 > /dev/null 2>&1
364    fi
365
366#           IGCM_debug_PopStack "IGCM_date_DaysInMonth"
367    return ;;
368  4|6|9|11)
369    if [ X$3 = X ] ; then
370      echo 30
371    else
372      eval $3=30 > /dev/null 2>&1
373    fi
374
375#           IGCM_debug_PopStack "IGCM_date_DaysInMonth"
376    return ;;
377  *) ;;
378  esac
379
380  # except for month 2 which depends on whether the year is a leap year
381  # Use IGCM_date_DaysInYear to get the number of days in the year and return a value
382  # accordingly.
383
384  IGCM_date_DaysInYear $y diy
385  case $diy in
386  365)
387    if [ X$3 = X ] ; then
388      echo 28
389    else
390      eval $3=28 > /dev/null 2>&1
391    fi
392
393#    IGCM_debug_PopStack "IGCM_date_DaysInMonth"
394    return ;;
395  366)
396    if [ X$3 = X ] ; then
397      echo 29
398    else
399      eval $3=29 > /dev/null 2>&1
400    fi
401
402#    IGCM_debug_PopStack "IGCM_date_DaysInMonth"
403    return ;;
404  esac
405
406#    IGCM_debug_PopStack "IGCM_date_DaysInMonth"
407}
408
409#D-#==================================================================
410#D-function IGCM_date_ConvertGregorianDateToJulian
411#D-* Purpose: Convert yyyymmdd to yyyyddd
412#D-* Usage: IGCM_date_ConvertGregorianDateToJulian 19980429
413#D-         if there is no command line argument, then assume that the date
414#D-         is coming in on a pipe and use read to collect it
415#D-
416function IGCM_date_ConvertGregorianDateToJulian
417{
418  IGCM_debug_PushStack "IGCM_date_ConvertGregorianDateToJulian" $@
419
420  # IGCM_date_ConvertGregorianDateToJulian converts yyyymmdd to yyyyddd
421  # usage IGCM_date_ConvertGregorianDateToJulian 19980429
422
423  typeset dt y m d x jul
424
425  # if there is no command line argument, then assume that the date
426  # is coming in on a pipe and use read to collect it
427  if [ $# = 0 ]
428  then
429    read dt
430  else
431    dt=$( IGCM_date_SupressZeros $1 )
432  fi
433
434  # break the yyyymmdd into separate parts for year, month and day
435  y=$(( $dt / 10000 ))
436  m=$(( ( $dt % 10000 ) / 100 ))
437  d=$(( ( $dt % 100 ) ))
438
439  # add the days in each month up to (but not including the month itself)
440  # into the days. For example if the date is 19980203 then extract the
441  # number of days in January and add it to 03. If the date is June 14, 1998
442  # then extract the number of days in January, February, March, April and May
443  # and add them to 14.
444  x=1
445  while [ $x -lt $m ]
446  do
447    IGCM_date_DaysInMonth $y $x md
448    d=$(( $d + $md ))
449    x=$(( $x + 1 ))
450  done
451
452  # combine the year and day back together again and you have the julian date.
453  jul=$(( ( $y * 1000 ) + $d ))
454  echo $jul
455
456  IGCM_debug_PopStack "IGCM_date_ConvertGregorianDateToJulian"
457}
458
459#D-#==================================================================
460#D-function IGCM_date_ConvertJulianDateToGregorian()
461#D-* Purpose: Convert yyyyddd to yyyymmdd
462#D-* Usage: IGCM_date_ConvertJulianDateToGregorian 1998213
463#D-         if there is no command line argument, assume one is being
464#D-         piped in and read it
465#D-
466function IGCM_date_ConvertJulianDateToGregorian
467{
468  IGCM_debug_PushStack "IGCM_date_ConvertJulianDateToGregorian" $@
469
470  # IGCM_date_ConvertJulianDateToGregorian converts yyyyddd to yyyymmdd
471  # usage IGCM_date_ConvertJulianDateToGregorian 1998213
472
473  typeset dt y m d grg
474
475  # if there is no command line argument, assume one is being
476  # piped in and read it
477  if [ X$1 = X ]
478  then
479    read dt
480  else
481    dt=$1
482  fi
483
484  # break apart the year and the days
485  y=$(( $dt / 1000 ))
486  d=$(( $dt % 1000 ))
487
488  # subtract the number of days in each month starting from 1
489  # from the days in the date. When the day goes below 1, you
490  # have the current month. Add back the number of days in the
491  # month to get the correct day of the month
492  m=1
493  while [ $d -gt 0 ]
494  do
495    IGCM_date_DaysInMonth $y $m md
496    d=$(( $d - $md ))
497    m=$(( $m + 1 ))
498  done
499
500  d=$(( $d + $md ))
501
502  # the loop steps one past the correct month, so back up the month
503  m=$(( $m - 1 ))
504
505  # assemble the results into a gregorian date
506  grg=$(( ( $y * 10000 ) + ( $m * 100 ) + $d ))
507  echo $( IGCM_date_GregorianDigit $grg )
508
509  IGCM_debug_PopStack "IGCM_date_ConvertJulianDateToGregorian"
510}
511
512#D-#==================================================================
513#D-function IGCM_date_AddDaysToJulianDate
514#D-* Purpose: Add days to a yyyyddd formatted date
515#D-* Usage: IGCM_date_AddDaysToJulianDate 1998312 { ,-}14
516#D-         Read the difference from the command lines
517#D-         and the date from the command line, or standard input
518#D-
519function IGCM_date_AddDaysToJulianDate
520{
521  IGCM_debug_PushStack "IGCM_date_AddDaysToJulianDate" $@
522
523  # IGCM_date_AddDaysToJulianDate adds days to a yyyyddd formatted date
524  # usage IGCM_date_AddDaysToJulianDate 1998312 { ,-}14
525
526  typeset dif yd d y
527
528  # Read the difference from the command lines
529  # and the date from the command line, or standard input
530  if [ X$2 = X ]
531  then
532    dif=$1
533    read yd
534  else
535    yd=$1
536    dif=$2
537  fi
538
539  # Break it into pieces
540  d=$(( $yd % 1000 ))
541  y=$(( $yd / 1000 ))
542
543  # Add the number of days (if days is negative this results is
544  # a subtraction)
545  d=$(( $d + $dif ))
546
547  # Extract the days in the year
548  IGCM_date_DaysInYear $y diy
549
550  # If the calculated day exceeds the days in the year,
551  # add one year to the year and subtract the days in the year from the
552  # calculated days. Extract the days in the new year and repeat
553  # test until you end up with a day number that falls within the
554  # days of the year
555  while [ $d -gt $diy ]
556  do
557    d=$(( $d - $diy ))
558    y=$(( $y + 1 ))
559    IGCM_date_DaysInYear $y diy
560  done
561
562  # This is the reverse process. If the calculated number of days
563  # is less than 1, move back one year. Extract
564  # the days in this year and add the days in the year
565  # loop on this test until you end up with a number that
566  # falls within the days of the year
567  while [ $d -lt 1 ]
568  do
569    y=$(( $y - 1 ))
570    IGCM_date_DaysInYear $y diy
571    d=$(( $d + $diy ))
572  done
573
574  # put the year and day back together and echo the result
575  yd=$(( ( $y * 1000 ) + $d ))
576
577  echo $yd
578
579  IGCM_debug_PopStack "IGCM_date_AddDaysToJulianDate"
580}
581
582#D-#==================================================================
583#D-function IGCM_date_AddDaysToGregorianDate
584#D-* Purpose: Add days to a yyyymmdd formatted date
585#D-* Usage: IGCM_date_AddDaysToGregorianDate 19980312 { ,-}14
586#D-         Read the difference from the command lines
587#D-         and the date from the command line, or standard input
588#D-
589function IGCM_date_AddDaysToGregorianDate
590{
591  IGCM_debug_PushStack "IGCM_date_AddDaysToGregorianDate" $@
592
593  # IGCM_date_AddDaysToGregorianDate adds days to a yyyymmdd formatted date
594  # usage IGCM_date_AddDaysToGregorianDate 19980312 { ,-}14
595
596  # Read the difference from the command lines
597  # and the date from the command line, or standard input
598  typeset dif yd tmp res
599  if [ X$2 = X ]
600  then
601    dif=$1
602    read yd
603  else
604    yd=$1
605    dif=$2
606  fi
607
608  tmp=$( IGCM_date_ConvertGregorianDateToJulian $yd )
609  tmp=$( IGCM_date_AddDaysToJulianDate $tmp $dif )
610  res=$( IGCM_date_ConvertJulianDateToGregorian $tmp )
611
612  echo $res
613
614  IGCM_debug_PopStack "IGCM_date_AddDaysToGregorianDate"
615}
616
617#D-#==================================================================
618#D-function IGCM_date_DaysBetweenJulianDate
619#D-* Purpose: Calculate the days difference between two dates and reports
620#D-           the number days as jul1 - jul2
621#D-* Usage: IGCM_date_DaysBetweenJulianDate jul1 jul2
622#D-         where julian date is in the form yyyyddd
623#D-
624function IGCM_date_DaysBetweenJulianDate
625{
626  IGCM_debug_PushStack "IGCM_date_DaysBetweenJulianDate" $@
627
628  # calculates the days difference between two dates and reports
629  # the number days as jul1 - jul2
630  # usage IGCM_date_DaysBetweenJulianDate jul1 jul2
631  # where julian date is in the form yyyyddd
632
633  usage () {
634    echo "Usage:"
635    echo " IGCM_date_DaysBetweenJulianDate jul1 jul2"
636    echo ""
637    echo " Calculates the day difference between"
638    echo " two julian dates (jul1 -jul2)"
639    echo " where a julian date is in the form of yyyyddd."
640  }
641
642  if [ $# -lt 2 ]; then
643    usage
644    IGCM_debug_Exit "IGCM_date_DaysBetweenJulianDate"
645  fi
646
647  typeset jul1 jul2 yyyy1 yyyy2 ddd1 ddd2 res
648
649  # This process subtracts arg2 from arg1. If arg2 is larger
650  # then reverse the arguments. The calculations are done, and
651  # then the sign is reversed
652  if [ $1 -lt $2 ]
653  then
654    jul1=$2
655    jul2=$1
656  elif [ $1 -gt $2 ]
657  then
658    jul1=$1
659    jul2=$2
660  else
661    echo 0
662    IGCM_debug_PopStack "IGCM_date_DaysBetweenJulianDate"
663    return
664  fi
665
666  # Break the dates in to year and day portions
667  yyyy1=$(( $jul1 / 1000 ))
668  yyyy2=$(( $jul2 / 1000 ))
669  ddd1=$(( $jul1 % 1000 ))
670  ddd2=$(( $jul2 % 1000 ))
671
672  # Subtract days
673  res=$(( $ddd1 - $ddd2 ))
674
675  # Then add days in year until year2 matches year1
676  case ${config_UserChoices_CalendarType} in
677  360d|360_day)
678    res=$(( ( ( $yyyy1 - $yyyy2 ) * 360 ) + $res )) ;;
679  noleap|365_day)
680    res=$(( ( ( $yyyy1 - $yyyy2 ) * 365 ) + $res )) ;;
681  all_leap|366_day)
682    res=$(( ( ( $yyyy1 - $yyyy2 ) * 366 ) + $res )) ;;
683  leap|gregorian|standard)
684    while [ $yyyy2 -lt $yyyy1 ]
685    do
686      IGCM_date_DaysInYear $yyyy2 diy
687      res=$(( $res + $diy ))
688      yyyy2=$(( $yyyy2 + 1 ))
689    done
690    ;;
691  esac
692
693  # if argument 2 was larger than argument 1 then
694  # the arguments were reversed before calculating
695  # adjust by reversing the sign
696  if [ $1 -lt $2 ]
697  then
698    res=$(( $res * -1 ))
699  fi
700
701  # and output the results
702  echo $res
703
704  IGCM_debug_PopStack "IGCM_date_DaysBetweenJulianDate"
705}
706
707#D-#==================================================================
708#D-function IGCM_date_DaysBetweenGregorianDate ()
709#D-* Purpose: Calculate the days difference between two dates and reports
710#D-           the number days as grg1 - grg2
711#D-* Usage: IGCM_date_DaysBetweenGregorianDate grg1 grg2
712#D-         where gregorian date is in the form yyyymmdd
713#D-
714function IGCM_date_DaysBetweenGregorianDate
715{
716  IGCM_debug_PushStack "IGCM_date_DaysBetweenGregorianDate" $@
717
718  # calculates the days difference between two dates and reports
719  # the number days as grg1 - grg2
720  # usage IGCM_date_DaysBetweenGregorianDate grg1 grg2
721  # where gregorian date is in the form yyyymmdd
722
723  usage () {
724    echo "Usage:"
725    echo " IGCM_date_DaysBetweenGregorianDate grg1 grg2"
726    echo ""
727    echo " Calculate day difference between"
728    echo " two gregorian dates (grg1 - grg2)"
729    echo " where a gregorian date is in the form of yyyymmdd."
730  }
731
732  if [ $# -lt 2 ]; then
733    usage
734    IGCM_debug_Exit "IGCM_date_DaysBetweenGregorianDate"
735  fi
736
737  typeset grg1 grg2 jul1 jul2 res
738
739  # convert each date to julian
740  grg1=$1
741  grg2=$2
742
743  jul1=$( IGCM_date_ConvertGregorianDateToJulian $grg1 )
744  jul2=$( IGCM_date_ConvertGregorianDateToJulian $grg2 )
745
746  if [ $jul1 -ne $jul2 ]; then
747    # calculate the answer using IGCM_date_DaysBetweenJulianDate
748    res=$( IGCM_date_DaysBetweenJulianDate $jul1 $jul2 )
749    # and output the results
750    echo $res
751  else
752    echo 0
753  fi
754
755  IGCM_debug_PopStack "IGCM_date_DaysBetweenGregorianDate"
756}
757
758#D-#==================================================================
759#D-function IGCM_date_DaysSinceJC ()
760#D-* Purpose: Calculate the days difference between a date and 00010101
761#D-* Usage: IGCM_date_DaysSinceJC grg1
762#D-         where gregorian date is in the form yyyymmdd
763#D-
764function IGCM_date_DaysSinceJC
765{
766  IGCM_debug_PushStack "IGCM_date_DaysSinceJC" $@
767
768  # calculates the days difference between a date and 00010101
769  # usage IGCM_date_DaysSinceJC grg1
770  # where gregorian date is in the form yyyymmdd
771
772  usage () {
773    echo "Usage:"
774    echo " IGCM_date_DaysSinceJC grg1"
775    echo ""
776    echo " Calculate day difference between"
777    echo " a gregorian date and 00010101"
778    echo " where a gregorian date is in the form of yyyymmdd."
779  }
780
781  if [ $# -lt 1 ]; then
782    usage
783    IGCM_debug_Exit "IGCM_date_DaysSinceJC"
784  fi
785
786  typeset aux num
787
788  if   [ ${1} -lt  5000000 ]; then
789    case ${config_UserChoices_CalendarType} in
790    360d|360_day)
791      aux=-360;;
792    noleap|365_day)
793      aux=-365;;
794    all_leap|366_day)
795      aux=-366;;
796    leap|gregorian|standard)
797      aux=-366;;
798    esac
799    num=101
800  elif [ ${1} -lt 15000000 ]; then
801    # To save CPU type we use auxiliary value
802    # which is number of days since JC and 10000101
803    case ${config_UserChoices_CalendarType} in
804    360d|360_day)
805      aux=359640;;
806    noleap|365_day)
807      aux=364635;;
808    all_leap|366_day)
809      aux=365634;;
810    leap|gregorian|standard)
811      aux=364877;;
812    esac
813    num=10000101
814  else
815    # To save CPU type we use auxiliary value
816    # which is number of days since JC and 19000101
817    case ${config_UserChoices_CalendarType} in
818    360d|360_day)
819      aux=683640;;
820    noleap|365_day)
821      aux=693135;;
822    all_leap|366_day)
823      aux=695034;;
824    leap|gregorian|standard)
825      aux=693595;;
826    esac
827    num=19000101
828  fi
829  echo $(( $( IGCM_date_DaysBetweenGregorianDate $1 ${num} ) + $aux ))
830
831  IGCM_debug_PopStack "IGCM_date_DaysSinceJC"
832}
833
834#D-#==================================================================
835#D-function IGCM_date_DaysInPreviousPeriod ()
836#D-* Purpose: Give the numbers of days during the previous prd1 period from grg1 date # OLD create_ts_begin_date
837#D-* Usage: IGCM_date_DaysInPreviousPeriod grg1 prd1 [end]
838#D-         where grg1 gregorian date is in the form yyyymmdd
839#D-         where prd1 period is in the form N[Yy], N[Mm], N[Dd]. N integer
840#D-         where [end] is an optionnal keyword to specify grg1 is the end of prd1
841#D-
842function IGCM_date_DaysInPreviousPeriod {
843  IGCM_debug_PushStack "IGCM_date_DaysInPreviousPeriod" $@
844
845  typeset Length Period year0 i
846
847  Period=${2}
848  case ${Period} in
849  *Y|*y)
850    PeriodLengthInYears=$( echo ${Period} | awk -F '[yY]' '{print $1}' )
851    IGCM_date_GetYearMonth ${1} year month
852    year=$( IGCM_date_SupressZeros ${year} )
853    if [ X${3} = Xend ] ; then
854      (( year = year - PeriodLengthInYears + 1))
855    fi
856    Length=0
857    i=0
858    until [ $i -ge $PeriodLengthInYears ] ; do
859      (( Length = Length + $( IGCM_date_DaysInYear $(( year + i )) ) ))
860      (( i = i + 1 ))
861    done
862    ;;
863  *M|*m)
864    PeriodLengthInMonths=$( echo ${Period} | awk -F '[mM]' '{print $1}' )
865    IGCM_date_GetYearMonth ${1} year month
866    year=$( IGCM_date_SupressZeros ${year} )
867    if [ X${3} = Xend ] ; then
868      (( month = month - PeriodLengthInMonths + 1 ))
869    fi
870    year0=year
871    if [ $month -le 0 ] ; then
872      (( month = month + 12 ))
873      year=$( printf "%04i\n" $(( year - 1 )) )
874    fi
875    month=$( printf "%02i\n" ${month} )
876    Length=0
877    i=0
878    until [ $i -ge $PeriodLengthInMonths ] ; do
879      if [ $(( month + i )) -lt 13 ] ; then
880        (( Length = Length + $( IGCM_date_DaysInMonth $year $(( month + i )) ) ))
881      else
882        (( year = year0 + 1 ))
883        (( Length = Length + $( IGCM_date_DaysInMonth $year $(( month + i - 12 )) ) ))
884      fi
885      (( i = i + 1 ))
886    done
887    ;;
888  *D|*d)
889    Length=$( echo ${Period} | sed -e "s/[dD]//" ) ;;
890  *)
891    IGCM_debug_Exit "IGCM_date_DaysInPreviousPeriod " ${Period} " invalid PeriodLength : choose in *Y, *M, *D."
892    IGCM_debug_Verif_Exit_Post ;;
893  esac
894  echo ${Length}
895
896  IGCM_debug_PopStack "IGCM_date_DaysInPreviousPeriod"
897}
898
899#D-#==================================================================
900#D-function IGCM_date_DaysInNextPeriod ()
901#D-* Purpose: Give the numbers of days during the next prd1 period from grg1 date # OLD create_ts_next_date
902#D-* Usage: IGCM_date_DaysInNextPeriod grg1 prd1
903#D-         where grg1 gregorian date is in the form yyyymmdd
904#D-         where prd1 period is in the form N[Yy], N[Mm], N[Dd]. N integer
905#D-
906function IGCM_date_DaysInNextPeriod {
907  IGCM_debug_PushStack "IGCM_date_DaysInNextPeriod" $@
908
909  typeset Length Period year0 month0 i
910
911  Period=${2}
912  case ${Period} in
913  *Y|*y)
914    PeriodLengthInYears=$( echo ${Period} | awk -F '[yY]' '{print $1}' )
915    IGCM_date_GetYearMonth ${1} year month
916    year=$( IGCM_date_SupressZeros ${year} )
917    Length=0
918    i=0
919    until [ $i -ge $PeriodLengthInYears ] ; do
920      (( Length = Length + $( IGCM_date_DaysInYear $(( year + i + 1 )) ) ))
921      (( i = i + 1 ))
922    done
923    ;;
924  *M|*m)
925    PeriodLengthInMonths=$( echo ${Period} | awk -F '[mM]' '{print $1}' )
926    IGCM_date_GetYearMonth ${1} year month
927    year=$( IGCM_date_SupressZeros ${year} )
928    year0=year
929    if [ $(( month + 1 )) -lt 13 ] ; then
930      month0=$(( month + 1 ))
931    else
932      month0=$(( month + 1 - 12 ))
933      (( year = year0 + 1 ))
934    fi
935    Length=0
936    i=0
937    until [ $i -ge $PeriodLengthInMonths ] ; do
938      if [ $(( month0 + i )) -lt 13 ] ; then
939        (( Length = Length + $( IGCM_date_DaysInMonth $year $(( month0 + i )) ) ))
940      else
941        (( year = year0 + 1 ))
942        (( Length = Length + $( IGCM_date_DaysInMonth $year $(( month0 + i - 12 )) ) ))
943      fi
944      (( i = i + 1 ))
945    done
946    ;;
947  *D|*d)
948    Length=$( echo ${Period} | sed -e "s/[dD]//" ) ;;
949  *)
950    IGCM_debug_Exit "IGCM_date_DaysInNextPeriod " ${Period} " invalid PeriodLength : choose in *Y, *M, *D."
951    IGCM_debug_Verif_Exit_Post ;;
952  esac
953  echo ${Length}
954
955  IGCM_debug_PopStack "IGCM_date_DaysInNextPeriod"
956}
957
958#D-#==================================================================
959#D-function IGCM_date_DaysInCurrentPeriod ()
960#D-* Purpose: Give the numbers of days during the Current prd1 period from grg1 date
961#D-* Usage: IGCM_date_DaysInCurrentPeriod grg1 prd1
962#D-         where grg1 gregorian date is in the form yyyymmdd
963#D-         where prd1 period is in the form N[Yy], N[Mm], N[Dd]. N integer
964#D-
965function IGCM_date_DaysInCurrentPeriod {
966  IGCM_debug_PushStack "IGCM_date_DaysInCurrentPeriod" $@
967
968  typeset Length Period year0 i
969
970  Period=${2}
971  case ${Period} in
972  *Y|*y)
973    PeriodLengthInYears=$( echo ${Period} | awk -F '[yY]' '{print $1}' )
974    IGCM_date_GetYearMonth ${1} year month
975    year=$( IGCM_date_SupressZeros ${year} )
976    month=$( IGCM_date_SupressZeros ${month} )
977    Length=0
978    # if starting after february and using leap calendar
979    # we need to add the number of days of the next year (potentially a leap year)
980    if [ ${month} -gt 2 ] ; then
981      (( year = year + 1 ))
982    fi
983    i=0
984    until [ $i -ge $PeriodLengthInYears ] ; do
985      (( Length = Length + $( IGCM_date_DaysInYear $(( year + i )) ) ))
986      (( i = i + 1 ))
987    done
988    ;;
989  *M|*m)
990    PeriodLengthInMonths=$( echo ${Period} | awk -F '[mM]' '{print $1}' )
991    IGCM_date_GetYearMonth ${1} year month
992    year=$( IGCM_date_SupressZeros ${year} )
993    year0=year
994    Length=0
995    i=0
996    until [ $i -ge $PeriodLengthInMonths ] ; do
997      if [ $(( month + i )) -lt 13 ] ; then
998        (( Length = Length + $( IGCM_date_DaysInMonth $year $(( month + i )) ) ))
999      else
1000        (( year = year0 + 1 ))
1001        (( Length = Length + $( IGCM_date_DaysInMonth $year $(( month + i - 12 )) ) ))
1002      fi
1003      (( i = i + 1 ))
1004    done
1005    ;;
1006  *D|*d)
1007    Length=$( echo ${Period} | sed -e "s/[dD]//" ) ;;
1008  *)
1009    IGCM_debug_Exit "IGCM_date_DaysInCurrentPeriod " ${Period} " invalid PeriodLength : choose in *Y, *M, *D."
1010    IGCM_debug_Verif_Exit_Post ;;
1011  esac
1012  echo ${Length}
1013
1014  IGCM_debug_PopStack "IGCM_date_DaysInCurrentPeriod"
1015}
1016
1017#D-#==================================================================
1018#D-function IGCM_date_Check
1019#D- * Purpose: Check the present file by comparison with a reference file
1020function IGCM_date_Check
1021{
1022  IGCM_debug_PushStack "IGCM_date_Check"
1023
1024#---------------------
1025  if [ ! -n "${libIGCM}" ] ; then
1026    echo "Check libIGCM_date ...........................................[ FAILED ]"
1027    echo "--Error--> libIGCM variable is not defined"
1028    IGCM_debug_Exit "IGCM_date_Check"
1029  fi
1030
1031#---------------------
1032  whence -v gawk > /dev/null 2>&1
1033  if [ ! $? -eq 0 ] ; then
1034    echo "Check libIGCM_date ...........................................[ FAILED ]"
1035    echo "--Error--> gawk command is not defined"
1036    IGCM_debug_Exit "IGCM_date_Check"
1037  fi
1038
1039#---------------------
1040  ${libIGCM}/libIGCM_date/IGCM_date_Test.ksh > IGCM_date_Test.ref.failed 2>&1
1041
1042  if diff IGCM_date_Test.ref.failed ${libIGCM}/libIGCM_date/IGCM_date_Test${dY}.ref > /dev/null 2>&1 ; then
1043    echo "Check libIGCM_date ...............................................[ OK ]"
1044    rm -f IGCM_date_Test.ref.failed
1045  else
1046    echo "Check libIGCM_date ...........................................[ FAILED ]"
1047    echo "--Error--> Execution of ${libIGCM}/libIGCM_date/IGCM_date_Test.ksh"
1048    echo "           has produced the file IGCM_date_Test.ref.failed"
1049    echo "           Please analyse differences with the reference file by typing:"
1050    echo "           diff IGCM_date_Test.ref.failed ${libIGCM}/libIGCM_date/IGCM_date_Test${dY}.ref"
1051    echo "           Report errors to the author: Sebastien.Denvil@ipsl.jussieu.fr"
1052    IGCM_debug_Exit "IGCM_date_Check"
1053  fi
1054
1055#---------------------
1056  IGCM_debug_PopStack "IGCM_date_Check"
1057}
1058
1059#==================================================================
Note: See TracBrowser for help on using the repository browser.