2

Bear with me I am not strong with bash. I have a date/time as in YYYYMMDDHHMMSS format such as 20031005000000in string. I like to add one year to it. I've read man date but it was a bit hard to interpret what it says although I think I do have basic understanding of -d and -s option looking at many examples from WWW.

These are a few of many I read:

So at the moment, I know how to add one year to current date.

myDatePlusOneYr=$(date -d "+365 days" '+%Y%m%d%H%M%S')

And I can add one year to date without having time segment (HHMMSS).

myDate="20031005"
date -d "$myDate +365 day"
Mon Oct  4 00:00:00 GMT 2004

However I have not found a way to add one year to a date/time format. When I tried with second option having with time segment, I get following error msg.

date: invalid date `20031005000000 +365 day'

I noticed backtick at the beginning of date/time and single quote at the end. I am not sure how to interpret the error msg. I'd appreciate your advice.

Update: I found an answer for invalid date: https://stackoverflow.com/questions/4197606/how-to-convert-yyyymmddhhmmss-to-a-date-readable-by-date

3 Answers 3

4

I might be over-simplifying it, but:

% expr 20091005000000 + 10000000000
20101005000000
3
  • I appreciate your reply. I didn't know about expr until now. I think I can parse out year and add 1 to it.
    – DaeYoung
    Aug 27, 2020 at 18:28
  • or only with bash: d=20031005000000; declare -i x; x=$d+10000000000; echo $x
    – Cyrus
    Aug 27, 2020 at 18:46
  • The user below is correct that this approach doesn't work if the day is February 29th.
    – Chris W.
    Sep 4, 2020 at 17:22
4

You could just treat the string as a number:

#/bin/sh
date='20000229000000'
echo "$((date + 10000000000))"

that prints 20041005000000. Of course it doesn't work correctly if your date happens to Feb 29th on a leap year, but that should be the only exception. You can deal with that by splitting the string to pieces and taking the leap day as a special case:

#!/bin/bash
date='20000229000000'
# assume it's correctly formatted
y=${date:0:4}
m=${date:4:2}
d=${date:6:2}
t=${date:8}

if [[ $m == 02 && $d == 29 ]]; then
        m=03
        d=01
fi

echo "$((y+1))$m$d$t"

In some shells, including Bash, the arithmetic treats numbers starting with zeroes as octal, but we're only doing arithmetic on the year, and it shouldn't have leading zeroes.

1

I don't like this answer because it invokes 3 shell commands to do it, but it works. Start with myDate="20031005010203"

I assume you want 1 year added to that. The ugly way is to take it apart, treat the first 8 characters as a YYYYMMDD, add a year, and use the date command to format the result. It stitches the time back onto the time value. Notice that for my test data I use 20040229 (a valid leap year).

myDate="20040229010203"
datebit=$(echo $myDate | cut -c 1-8)
timebit=$(echo $myDate | cut -c 9-)
newdate=$(date -d "$datebit +1 year" +"%Y%m%d${timebit}")
echo "${newdate}"

The input was 20040229010203 and the output should be 20050301010203.

So "one year from 01:02:03 on Feb 29 2004" is "01:02:03 on Mar 01 2005"

I tested this on ubuntu with the standard date command there.

1
  • Dammit. If I had just looked at @ikkachu's answer, I would see how to avoid most of these shell calls. But use date -d to do your math. Don't do special casing on february 29.
    – Paco Hope
    Aug 27, 2020 at 19:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .