I am using bash script and want to do a for loop of time from 3 hours ago to 3 hours later. For example, the pseudo codes follow:
time_end = 2000010100 #YYYYMMDDHH
time_beg = 1996010100 #YYYYMMDDHH
for time_beg -le time_end # while time_beg<=time_end
time_tmp = time_beg + 3 hours
do some calculation from time_beg to time_tmp
time_beg = time_tmp
end for
And the part do some calculation from time_beg to time_tmp is a model to simulate something from 1996-01-01-00 to 1996-01-01-03 (for example). Then next run would start from 1996-01-01-03 to 1996-01-01-06.
To do the part of time_tmp = time_beg + 3 hours, I use following codes:
YMDH=$YYYYMMDDHH
time_resolution=3
INC=+${time_resolution}hours
YMDH_newend=`date +%Y%m%d%H -d "${YMDH::8} ${YMDH:8:2} ${INC}"`
echo ${YMDH_newend}
I tested it worked well but got an error when $YYYYMMDDHH=1996033101. Running the codes above yield results of $YYYYMMDDHH=1996033105 which is wrong and should be $YYYYMMDDHH=1996033104…
So what happened? or is there any smarter way to do this? like using python? something like $(python -c "print(blablabla about YYYYMMDDHH)")?
Thanks!
>Solution :
The issue you’re encountering is likely due to Daylight Saving Time. On March 31, 1996, many countries moved their clocks forward one hour at 1:00 AM, effectively skipping the hour from 2:00 AM to 3:00 AM. This is why when you add 3 hours to 1:00 AM, you end up at 5:00 AM instead of 4:00 AM.
If you want to avoid this issue, you can use UTC time, which does not observe Daylight Saving Time. You can specify UTC time in the date command by appending a Z to the time string:
YMDH=$YYYYMMDDHH
time_resolution=3
INC=+${time_resolution}hours
YMDH_newend=`date -u +%Y%m%d%H -d "${YMDH::8}T${YMDH:8:2}Z ${INC}"`
echo ${YMDH_newend}
Note the -u option in the date command, which tells it to use UTC time, and the T and Z in the date string, which specify the time in ISO 8601 format in UTC.
Alternatively, you can use Python to do the date arithmetic, which can handle these edge cases more gracefully:
YMDH=$YYYYMMDDHH
time_resolution=3
YMDH_newend=$(python -c "from datetime import datetime, timedelta; dt = datetime.strptime('$YMDH', '%Y%m%d%H'); dt += timedelta(hours=$time_resolution); print(dt.strftime('%Y%m%d%H'))")
echo ${YMDH_newend}
This Python script parses the date string into a datetime object, adds the specified number of hours to it, and then formats it back into a string.