Index: TOOLS/WATER_BUDGET/WaterUtils.py
===================================================================
--- TOOLS/WATER_BUDGET/WaterUtils.py	(revision 6518)
+++ TOOLS/WATER_BUDGET/WaterUtils.py	(revision 6620)
@@ -1,34 +1,40 @@
 #!/usr/bin/env python3
-###
-### Script to check water conservation in the IPSL coupled model
-###
-## Here, some common utilities to all scripts
-##
-##  Warning, to install, configure, run, use any of included software or
-##  to read the associated documentation you'll need at least one (1)
-##  brain in a reasonably working order. Lack of this implement will
-##  void any warranties (either express or implied).  Authors assumes
-##  no responsability for errors, omissions, data loss, or any other
-##  consequences caused directly or indirectly by the usage of his
-##  software by incorrectly or partially configured personal
-##
-##
-## SVN information
-#  $Author$
-#  $Date$
-#  $Revision$
-#  $Id: ATM_waterbudget.py 6277 2022-12-08 09:24:05Z omamce $
-#  $HeadURL$
-
-## Import system modules
-#import sys, os, shutil, subprocess, platform
+'''
+  Script to check water conservation in the IPSL coupled model
+ 
+  Here, some common utilities to all scripts
+   
+  Warning, to install, configure, run, use any of included software or
+  to read the associated documentation you'll need at least one (1)
+  brain in a reasonably working order. Lack of this implement will
+  void any warranties (either express or implied).  Authors assumes
+  no responsability for errors, omissions, data loss, or any other
+  consequences caused directly or indirectly by the usage of his
+  software by incorrectly or partially configured personal
+
+
+ SVN information
+ $Author$
+ $Date$
+ $Revision$
+ $Id: ATM_waterbudget.py 6277 2022-12-08 09:24:05Z omamce $
+ $HeadURL$
+'''
+
 import numpy as np
 import configparser, re
 
-VarInt = 10
-Ra     = None
-
-def ftest () :
-    print ( toto )
+VarInt      = 10
+Rho         = 1000.0
+Ra          = 6366197.7236758135 #-- Earth Radius (m)
+Grav        = 9.81               #-- Gravity (m^2/s
+ICE_rho_ice = 917.0              #-- Ice volumic mass (kg/m3) in LIM3
+ICE_rho_sno = 330.0              #-- Snow volumic mass (kg/m3) in LIM3
+OCE_rho_liq = 1026.0             #-- Ocean water volumic mass (kg/m3) in NEMO
+ATM_rho     = 1000.0             #-- Water volumic mass in atmosphere (kg/m^3)
+SRF_rho     = 1000.0             #-- Water volumic mass in surface reservoir (kg/m^3)
+RUN_rho     = 1000.0             #-- Water volumic mass of rivers (kg/m^3)
+ICE_rho_pnd = 1000.              #-- Water volumic mass in ice ponds (kg/m^3)
+YearLength  = 365.25 * 24. * 60. * 60. #-- Year length (s)
 
 def setBool (chars) :
@@ -43,5 +49,5 @@
     '''Convert specific char string in integer or real if possible'''
     if type (chars) == str :
-        realnum = re.compile ("^[-+]?[0-9]*\.?[0-9]+(e[-+]?[0-9]+)?$")
+        realnum  = re.compile ("^[-+]?[0-9]*\.?[0-9]+(e[-+]?[0-9]+)?$")
         isNumber = realnum.match(chars.strip()) != None
         isInt    = chars.strip().isdigit()
@@ -63,9 +69,18 @@
 
 def unDefined (char) :
-    if char in globals () :
-        if globals()[char] == None : unDefined = True
+    '''True if a variable is not defined, or set to None'''
+    if char in locals () :
+        if locals()[char] == None : unDefined = True
         else            : unDefined = False
     else                : unDefined = True
     return unDefined
+
+def Defined (char) :
+    '''True if a variable is defined and not equal to None'''
+    if char in globals () :
+        if globals()[char] == None : Defined = False
+        else            : Defined = True
+    else                : Defined = False
+    return Defined
 
 def Ksum (tab) :
@@ -87,5 +102,5 @@
 def Ssum (tab) :
     '''
-    Precision summation by sorting by absolute value
+    Precision summation by sorting by absolute values
     '''
     Ssum = np.sum ( tab[np.argsort(np.abs(tab))] )
@@ -102,5 +117,132 @@
 Psum = KSsum
 
-
-
-
+def IsLeapYear ( Year, CalendarType="Gregorian" ) :
+    ''' True is Year is a leap year ''' 
+
+    # What is the calendar :
+    if CalendarType in [ '360d', '360_day', 'noleap', '365_day'] : 
+        IsLeapYear = False
+        return IsLeapYear
+
+    if CalendarType in [ 'all_leap', '366_day' ] : 
+        IsLeapYear = True
+        return IsLeapYear
+    
+    Year = int ( Year )
+  
+    # a year is a leap year if it is even divisible by 4
+    # but not evenly divisible by 100
+    # unless it is evenly divisible by 400
+
+    # if it is evenly divisible by 400 it must be a leap year
+    if np.mod ( Year, 400 ) == 0 : 
+        IsLeapYear = True
+        return IsLeapYear
+        
+    # if it is evenly divisible by 100 it must not be a leap year
+    if np.mod ( Year, 100 ) == 0 :
+        IsLeapYear = False
+        return IsLeapYear
+
+    # if it is evenly divisible by 4 it must be a leap year
+    if np.mod ( Year, 4 ) == 0 :
+        IsLeapYear = True
+        return IsLeapYear
+
+    IsLeapYear = False
+    return IsLeapYear
+
+def DateFormat ( Date ) :
+    '''
+    Get date format :
+      [yy]yymmdd   is Gregorian
+      [yy]yy-mm-dd is Human
+    '''
+    if type (Date) == str :
+        if '-' in Date : 
+            DateFormat = 'Human'
+        else : 
+            DateFormat = 'Gregorian'
+    if type (Date) == int : DateFormat = 'Gregorian'
+    return DateFormat
+
+def PrintDate ( YE, MO, DA, Format ) :
+    '''Return a date in the requested format'''
+    if Format == 'Human'     : PrintDate = f'{YE:04d}-{MO:02d}-{DA:02d}'
+    if Format == 'Gregorian' : PrintDate = f'{YE:04d}{MO:02d}{DA:02d}'
+    return PrintDate
+        
+def FormatToGregorian ( Date ) :
+    ''' from a yyyy-mm-dd or yyymmdd date format returns
+        a yyymmdd date format
+    '''
+    YE, MO, DA = SplitDate ( Date )
+    FormatToGregorian = f'{YE:04d}{MO:02d}{DA:02d}'
+    return FormatToGregorian
+  
+def FormatToHuman ( Date ) :
+    ''' From a yyyymmdd or yyymmdd date format returns
+        a yyy-mm-dd date format
+    '''
+    YE, MO, DA = SplitDate ( Date )
+    FormatToHuman =  f'{YE_new:04d}-{MO:02d}-{DA:02d}'
+    return FormatToHuman
+
+def SplitDate  ( Date, Out='int' ) :
+    ''' Split Date in format [yy]yymmdd or [yy]yy-mm-dd
+        to yy, mm, dd '''
+    if type (Date) == str :
+        if '-' in Date : 
+            Dash = True
+            YE, MO, DA = Date.split ('-')
+        else : 
+            Dash = False
+            YE = Date[:-4] ; MO = Date[-4:-2] ; DA = Date[-2:]
+            YearDigits = len (YE)
+    if type (Date) == int :
+        DA = np.mod ( Date, 100) 
+        MO = np.mod ( Date//100, 100)
+        YE = Date // 10000
+    
+    YE = int(YE) ; MO = int(MO) ; DA=int(DA)
+    return YE, MO, DA
+
+def DateAddYear ( Date, YearInc=1 ) :
+    ''' Add on year to date in format [yy]yymmdd or [yy]yy-mm-dd'''
+    Format = DateFormat ( Date )
+    YE, MO, DA = SplitDate ( Date )
+    YE_new = YE + YearInc
+    DateAddYear = PrintDate ( YE_new, MO, DA, Format)
+    return DateAddYear 
+
+def DateMinusOneDay ( Date ) :
+    ''' Substracts one day to date in format [yy]yymmdd or [yy]yy-mm-dd'''
+    Format = DateFormat ( Date )
+    mth_length = np.array ( [31, 28, 31,  30,  31,  30,  31,  31,  30,  31,  30,  31] )
+    YE, MO, DA = SplitDate ( Date )
+    if IsLeapYear ( YE) : mth_length[1] += 1
+    
+    YE = int(YE) ; MO = int(MO) ; DA=int(DA)
+    if DA ==  1 : 
+        if MO == 1 : DA_new = mth_length[-1]   ; MO_new = 12     ; YE_new = YE - 1
+        else       : DA_new = mth_length[MO-2] ; MO_new = MO - 1 ; YE_new = YE
+    else        :    DA_new = DA - 1           ; MO_new = MO     ; YE_new = YE
+
+    DateMinusOneDay = PrintDate ( YE_new, MO_new, DA_new, Format)
+    return DateMinusOneDay
+
+def DatePlusOneDay ( Date ) :
+    ''' Add one day to date in format [yy]yymmdd or [yy]yy-mm-dd'''
+    Format = DateFormat ( Date )
+    mth_length = np.array ( [31, 28, 31,  30,  31,  30,  31,  31,  30,  31,  30,  31] )
+    YE, MO, DA = SplitDate ( Date )
+    if IsLeapYear ( YE ) : mth_length[1] += 1
+    
+    YE_new = YE ; MO_new=MO ; DA_new=DA+1
+    if DA_new > mth_length [MO_new-1] :
+        DA_new = 1 ; MO_new = MO_new + 1
+        if MO_new == 13 : 
+            MO_new = 1 ; YE_new = YE_new+1
+
+    DatePlusOneDay = PrintDate ( YE_new, MO_new, DA_new, Format )
+    return DatePlusOneDay
