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

Last change on this file since 589 was 589, checked in by acosce, 12 years ago

ACo : bugfix affecting the calcul of the date for restart and debug pack

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