Search code examples
bashdategnu

Generate all dates between two dates in %Y-%m-%d-%H format in bash


Using bash I want to generate all dates between, say, 2023-11-04-00 and 2023-11-06-00 where the format is %Y-%m-%d-%H. I have tried :

#!/bin/bash

d=2023-11-04
while [ "$d" != 2023-11-06 ]; do
        d=$(date -d "$d 1 hour")
        u=$(date -d "$d" +'%Y-%m-%d-%H')
        echo $u
done

It works but I get an infinite loop and can't quite figure out what is happening.


Solution

  • Rather than performing hazardous and non locale-agnostic date arithmetic, using a unix timestamp ensures consistent results

    Using Bash grammar:

    #!/usr/bin/env bash
    
    start_date=2023-11-04
    end_date=2023-11-06
    
    start_ts=$(date -d "$start_date" +%s)
    end_ts=$(date -d "$end_date" +%s)
    
    for ((ts=start_ts; ts<=end_ts; ts+=3600))
    do printf '%(%Y-%m-%d-%H)T\n' "$ts"
    done
    

    Using POSIX-shell grammar:

    #!/usr/bin/env sh
    
    start_date=2023-11-04
    end_date=2023-11-06
    
    start_ts=$(date -d "$start_date" +%s)
    end_ts=$(date -d "$end_date" +%s)
    
    ts=$start_ts
    while [ "$ts" -le "$end_ts" ]
    do
      date -d "@$ts" +'%Y-%m-%d-%H' 
      ts=$((ts + 3600))
    done