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

Last change on this file since 1206 was 1206, checked in by sdipsl, 9 years ago
  • Remove IGCM_debug_Verif_Exit_Post. Only IGCM_debug_Verif_Exit will manage exit cases.
  • 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
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.