# Functions to handle date/time information # Default "rule" for Hayasaki # * This file must be stored under $HOME/bin/function/. # # last update: 2013-08-09 # written by M. Hayasaki (Univ. Tsukuba, Japan) # # update: 2011-06-30 # written by M. Hayasaki (Univ. Toyama, Japan) # # List of functions # (func name) (input) (output) # * utc2jst : 2, utc_yyyymmddHH : 1, jst_yyyymmddHH # * jst2utc : 2, jst_yyyymmddHH : 1, utc_yyyymmddHH # * get_today : none : 1, TODAY (Date represented as "28 January 2009" style) # * doy2yyyymmdd : 2, year, doy : 1, yyyymmdd # * yyyymmdd2doy : 3, year, mm, dd : 1, doy # * doy2dd : 2, year, doy : 1, dd # * doy2mm : 2, year, doy : 1, mm # * doy2cmon : 2, year, doy : 1, cmon (abbreviated month name) # * doy2yyyy : 2, year, doy : 1, year (!! This function is dummy !!) # * doy2yymm : 2, year, doy : 1, yymm (2-digit year & month) # * yyyymmddHH_split : 1, yyyymmddHH : 4, yyyy, mm, dd, HH # * yyyymmdd_split : 1, yyyymmdd : 3, yyyy, mm, dd # * return_total_months : 2, s_yyyymm, e_yyyymm : 1, total_month (number of months) # * return_total_days : 2, s_yyyymmdd, e_yyyymmdd : 1, total_day # * set_twomon_param : 1, twomon_ID (JF, MA, ..., ND) : 5, cperiod, smm, emm, twomon_num, period_num # * set_common_yr_flag : 1, year : common_yr (Set 0 or 1, 1: common year, 0: leap year) # * return_center_mon : 1, season (DJF, etc.) : center_mon (in 2-digit number. 01, 04, 07, 10) function utc2jst { local lcl_fnc_name="utc2jst" ### [Example] ### Input: 2011062912 (i.e., 12 UTC June 29, 2011) ### Output: 2011062921 (i.e., 21 JST June 29, 2011) utc_yyyymmddHH=$1 # ex. "2011062912" style if [ $# -eq 2 ]; then selector=$2 # Set output style elif [ $# -eq 1 ]; then selector=numeric # Default fi if [ ${#utc_yyyymmddHH} -ne 10 ]; then echo -e "\t[Function ${lcl_fnc_name}]" echo "Length of shelll variable is NOT equal to 10." echo "Stopped." exit 901 fi # -n $variable <= Return "TRUE" if $variable is NOT null. if [ -n $selector ]; then case $selector in numeric) jst_yyyymmddHH=`\date --date="${utc_yyyymmddHH:8:2}UTC ${utc_yyyymmddHH:0:8}" +"%Y%m%d%H"` ;; iso) # ISO 8601 style "2011-06-29T21:00:00+09:00" jst_yyyymmddHH=`\date --date="${utc_yyyymmddHH:8:2}UTC ${utc_yyyymmddHH:0:8}" +"%Y-%m-%dT%H:00:00+09:00"` ;; *) echo "Undefined selector. Stopped function utc2jst" exit 988 ;; esac else # Default style: "2011062921" jst_yyyymmddHH=`\date --date="${utc_yyyymmddHH:8:2}UTC ${utc_yyyymmddHH:0:8}" +"%Y%m%d%H"` fi } # END of function utc2jst function jst2utc { local lcl_fnc_name="jst2utc" ### [Example] ### Input: 2011062921 (i.e., 21 JST June 29, 2011) ### Output: 2011062912 (i.e., 12 UTC June 29, 2011) jst_yyyymmddHH=$1 # ex. "2011062912" style if [ $# -eq 2 ]; then selector=$2 # Set output style elif [ $# -eq 1 ]; then selector=numeric # Default fi if [ ${#jst_yyyymmddHH} -ne 10 ]; then echo -e "\t[Function ${lcl_fnc_name}]" echo "Length of shelll variable is NOT equal to 10." echo "Stopped." exit 902 fi # -n $variable <= Return "TRUE" if $variable is NOT null. if [ -n $selector ]; then case $selector in numeric) utc_yyyymmddHH=`\date --utc --date="${jst_yyyymmddHH:8:2}JST ${jst_yyyymmddHH:0:8}" +"%Y%m%d%H"` ;; iso) # ISO 8601 style "2011-06-29T21:00:00+09:00" utc_yyyymmddHH=`\date --utc --date="${jst_yyyymmddHH:8:2}JST ${jst_yyyymmddHH:0:8}" +"%Y-%m-%dT%H:00:00+09:00"` ;; *) echo "Undefined selector. Stopped function jst2utc" exit 988 ;; esac else # Default style: "2011062921" utc_yyyymmddHH=`\date --utc --date="${jst_yyyymmddHH:8:2}JST ${utc_yyyymmddHH:0:8}" +"%Y%m%d%H"` fi } # END of function jst2utc function get_today { local lcl_fnc_name="get_today" ### Output format: 28 January 2009 TODAY=`LANG=C ; \date +"%d %B %Y"` echo -e "\t function ${lcl_fnc_name}: TODAY = ${TODAY}" } # END of function get_today ### Gives 4-digit year, and DOY, ### Return 8-digit date in the form "YYYYMMDD" function doy2yyyymmdd { local lcl_fnc_name="doy2yyyymmdd" if [ $# -ne 2 ] ; then echo "Argument mismatch." echo " ** Usage: doy2yyyymmdd 2009 30" return 1 exit 976 fi year=$1 doy=$2 target_date=`LANG=C ; \date --date="01/01/${year} +${doy} day - 1 day" +"%Y%m%d"` } # End "doy2yyyymmdd" ### Gives 4-digit year, 1- or 2-digit month or day, ### Return "Day of Year" function yyyymmdd2doy { local lcl_fnc_name="yyyymmdd2doy" if [ $# -ne 3 ] ; then echo -e "\t[Function ${lcl_fnc_name}]" echo "Argument mismatch." echo " ** Usage: yyyymmdd2doy 2012 03 25" return 1 exit 976 fi local year=$1 local month=$2 local day=$3 doy=`LANG=C ; \date --date="${month}/${day}/${year}" +%j` } # END of function yyyymmdd2doy ### Series: doy2* functions ### Gives year and "day of year", ### Return mm, dd, and cmm (month written in character) function doy2dd { local lcl_fnc_name="doy2dd" year=$1 # calendar year doy=$2 # calendar month if [ $doy -gt 366 ] ; then echo -e "\t[Function ${lcl_fnc_name}]" echo "CAUTION: Too large number in DOY field (\$2). Stopped." exit fi dd=`LANG=C ; \date --date="01/01/${year} -1day +${doy}day" +%d` } # End "doy2dd" function doy2mm { year=$1 doy=$2 mm=`LANG=C ; \date --date="01/01/${year} -1day +${doy}day" +%m` } function doy2cmon { year=$1 doy=$2 cmon=`LANG=C ; \date --date="01/01/${year} -1day +${doy}day" +%b` } function doy2yyyy { year=$1 doy=$2 yyyy=`LANG=C ; \date --date="01/01/${year} -1day +${doy}day" +%Y` } function doy2yymm { year=$1 doy=$2 # return 2-digit year & month yymm=`LANG=C ; \date --date="01/01/${year} -1day +${doy}day" +%y%m` } ### Gives 10-digit date/time (yyyymmddHH) ### Return $yyyy, $mm, $dd, $HH function yyyymmddHH_split { local lcl_fnc_name="yyyymmddHH_split" local yyyymmddHH=$1 if [ ${#yyyymmddHH} -eq 10 ]; then yyyy=${yyyymmddHH:0:4} mm=${yyyymmddHH:4:2} dd=${yyyymmddHH:6:2} HH=${yyyymmddHH:8:2} else echo -e "\t[Function ${lcl_fnc_name}]" echo "Length of shelll variable is NOT equal to 10." echo "Stopped (exit 996)" exit 996 fi } # End of function yyyymmddHH_split ### Gives 8-digit date (yyyymmdd) ### Return $yyyy, $mm, $dd function yyyymmdd_split { local lcl_fnc_name="yyyymmdd_split" local lcl_yyyymmdd=$1 if [ ${#lcl_yyyymmdd} -eq 8 ]; then yyyy=${lcl_yyyymmdd:0:4} mm=${lcl_yyyymmdd:4:2} dd=${lcl_yyyymmdd:6:2} ### Make "01Jan2001" style date parameter (ddbbyyyy; Available for "set time" commands in GrADS) ### Called from "111_point_read_fwrite_daily_mean.sh" under ~/JRA/point/ ### (1st append at: 2014-05-17) ddbbyyyy=`LANG=C ; \date --date="${lcl_yyyymmdd}" +"%d%b%Y"` else echo -e "\t[Function ${lcl_fnc_name}]" echo "Length of shelll variable is NOT equal to 8." echo "Stopped (exit 994)" exit 994 fi } # End of function yyyymmdd_split ### Gives start and end of date (YYYYMM), ### Return "Total number of months" function return_total_months { local lcl_fnc_name="return_total_months" if [ $# -lt 2 ]; then echo -e "\t[Function ${lcl_fnc_name}]" echo "***** Too short arguments. Stopped (exit8). *****" echo -e "\t Usage: return_total_months s_YYYYMM e_YYYYMM" echo -e "(Give two arguments, then return shell variable \$total_month)" exit 8 fi local local_s_yyyymm=$1 local local_e_yyyymm=$2 if [ ${#local_s_yyyymm} -ne 6 -o ${#local_e_yyyymm} -ne 6 ]; then echo "func ${lcl_fnc_name}: Character length mismatch. Stopped." exit 886 fi # echo "No. of characters (s_yyyymm) = ${#s_yyyymm}" # echo "No. of characters (e_yyyymm) = ${#e_yyyymm}" local lcl_cnt=0 local local_yyyymm=${local_s_yyyymm} while [ $local_yyyymm -le ${local_e_yyyymm} ]; do lcl_cnt=`expr $lcl_cnt + 1` local_yyyymm=`\date --date="${local_yyyymm}01 +1 month" +"%Y%m"` done # yyyymm total_month=${lcl_cnt} unset lcl_cnt } # End of function return_total_months ### Gives start and end of date (YYYYMMDD), ### Return "Total number of days (${total_day})" function return_total_days { local lcl_fnc_name="return_total_days" if [ $# -lt 2 ]; then echo -e "\t[Function ${lcl_fnc_name}]" echo "***** Too short arguments. Stopped (exit8). *****" echo -e "\t Usage: ${lcl_fnc_name} s_YYYYMMDD e_YYYYMMDD" echo -e "(Give two arguments, then return shell variable \$total_day)" exit 8 fi local s_yyyymmdd=$1 local e_yyyymmdd=$2 ### Check input arguments if [ $e_yyyymmdd -lt $s_yyyymmdd ]; then echo -e "\t[Function ${lcl_fnc_name}]" echo -e "\t Wrong date. Stopped (exit 9)." echo -e "\t Check your argument: sdate = $s_yyyymmdd ; edate = $e_yyyymmdd " exit 9 fi # echo -e "\t sdate = $s_yyyymmdd ; edate = $e_yyyymmdd " local syyyy=${s_yyyymmdd:0:4} local next_yr=`expr $syyyy + 1` local eyyyy=${e_yyyymmdd:0:4} local before_yr=`expr $eyyyy - 1` local diff_yr=`expr $eyyyy - $syyy + 1` ### count DOY in the begin year local doy_syy_target=`\date --date="${s_yyyymmdd}" +%j` local doy_syy_31dec=`\date --date="12/31/${syyyy}" +%j` local doy_syy_total=`expr $doy_syy_31dec - $doy_syy_target + 1` ### count DOY in the end of year local doy_eyy_target=`\date --date="${e_yyyymmdd}" +%j` ### count DOY in the period of (begin + 1) - (end - 1) year if [ $syyyy -eq $eyyyy ]; then total_day=`echo "$doy_eyy_target - $doy_syy_target + 1" | bc -q` # echo -e "\t Total Days in syy = $doy_syy_target " # echo -e "\t Total Days in eyy = $doy_eyy_target " # echo -e "\t Total Days = $total_day " elif [ $diff_yr -eq 1 ]; then total_day=`echo "$doy_eyy_target + $doy_syy_total" | bc -q` # echo -e "\t Total Days in syy = $doy_syy_total " # echo -e "\t Total Days in eyy = $doy_eyy_target " # echo -e "\t Total Days = $total_day " elif [ $diff_yr -ge 2 ]; then local sum_doy=0 local yyyy=`expr $syyyy + 1` while [ $yyyy -le $before_yr ]; do local doy=`\date --date="12/31/${yyyy}" +%j` local sum_doy=`expr $sum_doy + $doy` yyyy=`expr $yyyy + 1` done # yyyy total_day=`expr $doy_syy_total + $sum_doy + $doy_eyy_target` echo -e "\t function ${lcl_fnc_name}: Total Days = ${total_day}" fi unset lcl_fnc_name } # End of function return_total_days ##### function set_twomon_param { local twomon_ID=$1 # JF, MA, MJ, JA, SO, ND case $twomon_ID in JF) cperiod="Jan-Feb" smm=01 emm=02 twomon_num=1 ;; MA) cperiod="Mar-Apr" smm=03 emm=04 twomon_num=2 ;; MJ) cperiod="May-Jun" smm=05 emm=06 twomon_num=3 ;; JA) cperiod="Jul-Aug" smm=07 emm=08 twomon_num=4 ;; SO) cperiod="Sep-Oct" smm=09 emm=10 twomon_num=5 ;; ND) cperiod="Nov-Dec" smm=11 emm=12 twomon_num=6 ;; *) echo -e "\t Warning: Undefined twomon_ID (${twomon_ID})" echo -e "\t (You can use JA, MA, MJ, JA, SO, ND)" echo -e "\t (See function set_twomon_param in ${func_name}" exit 98 ;; esac period_num=${twomon_num} echo -e "\t Returned values = cperiod ($cperiod) ; smm, emm = ($smm, $emm)" } # End of function set_twomon_param # Set lev_var (ex. 0500HGT) function set_lev_var { local lcl_fnc_name="set_lev_var" lcl_var=$1 lcl_lev_4digit=$2 # FIXED to 4-digit case $lcl_lev in 1013) lev_var=${lcl_var} ;; *) lev_var=${lcl_lev_4digit}${lcl_var} ;; esac } # END function set_lev_var # Check common year ($common_yr=1) or leap year ($common_yr=0) function set_common_yr_flag { local lcl_fnc_name="set_common_yr_flag" ### [Example] ### Input: set_common_yr_flag 2011 ### Output: (return shell variable $common_yr) lcl_yy=$1 lcl_num_doy=`LANG=C ; \date --date="12/31/${lcl_yy}" +%j` if [ $lcl_num_doy -eq 366 ] ; then common_or_leap=0 # leap year else common_or_leap=1 # common year (set true flag) fi } # END function set_common_yr_flag function return_center_mon { local lcl_fnc_name="return_center_mon" local lcl_cseason=$1 # DJF, JJA, MAM, SON, etc. case $lcl_cseason in DJF) center_mon=01 ;; MAM) center_mon=04 ;; JJA) center_mon=07 ;; SON) center_mon=10 ;; *) echo " FUNC ${lcl_fnc_name}: Undefined season. Stopped." echo " Check ${lcl_fnc_name} in get_dateinfo under ~/bin/function/." ;; esac } # * return_center_mon : 1, season : center_mon (in 2-digit number) function set_num_mon { local lcl_fnc_name="set_num_mon" local lcl_period_ID=$1 local lcl_num_yr=$2 case $lcl_period_ID in [0-9][0-9]) num_mon=${lcl_num_yr} # monthly ;; ND|DJ|JF|FM|MA) # for two-month period num_mon=$(echo "2 * ${lcl_num_yr}" | bc -q) ;; DJF|MAM|JJA|SON) # for DJF, MAM, JJA, SON (standard 3-mon season) num_mon=$(echo "3 * ${lcl_num_yr}" | bc -q) ;; DJFM) # for DJFM num_mon=$(echo "4 * ${lcl_num_yr}" | bc -q) ;; NDJFM) # for NDJFM num_mon=$(echo "5 * ${lcl_num_yr}" | bc -q) ;; esac } # END function set_num_mon function set_cperiod { local lcl_fnc_name="set_cperiod" local lcl_period_ID=$1 case $lcl_period_ID in 01|02|03|04|05|06|07|08|09|10|11|12) cperiod=m${lcl_period_ID} # "m01" ;; *) # Default: NDJFM, DJF, DJFM, ... cperiod=${lcl_period_ID} # seasonal (DJF, DJFM, NDJFM, etc.) ;; esac } # END function set_cperiod