--- /dev/null
+#!/bin/sh
+
+isdate(){
+ local date="$1" y m d
+
+ if printf %s "$date" \
+ | grep -xEq '[0-9]{4}-((01|03|05|07|08|10|12)-(0[1-9]|[12][0-9]|3[01])|(04|06|09|11)-(0[1-9]|[12][0-9]|30)|02-(0[1-9]|[12][0-9]))'
+ then # y-m-d (ISO Date)
+ y="${date%%-*}" d="${date##*-}" m="${date%-*}" m="${m#*-}"
+ elif printf %s "$date" \
+ | grep -xEq '((0?1|0?3|0?5|0?7|0?8|10|12)/(0?[1-9]|[12][0-9]|3[01])|(0?4|0?6|0?9|11)/(0?[1-9]|[12][0-9]|30)|0?2-(0[1-9]|[12][0-9]))/([0-9]{2}|[0-9]{4
+})'
+ then # m/d/y (US Date)
+ y="${date##*/}" m="${date%%/*}" d="${date%/*}" d="${d#*/}"
+ elif printf %s "$date" \
+ | grep -xEq '((0?[1-9]|[12][0-9]|3[01])[\./](0?1|0?3|0?5|0?7|0?8|10|12)|(0?[1-9]|[12][0-9]|30)[\./](0?4|0?6|0?9|11)|(0[1-9]|[12][0-9])[\./]0?2)[\./](
+[0-9]{2}|[0-9]{4})'
+ then # d/m/y or d.m.y (European Date / German Date)
+ y="${date##*.}" d="${date%%.*}" m="${date%.*}" m="${m#*.}"
+ else
+ return 1
+ fi
+ [ $y -lt 100 -a $y -gt 50 ] && y=$((y + 1900))
+ [ $y -lt 100 -a $y -le 50 ] && y=$((y + 2000))
+ date="$(printf "%04i-%02i-%02i" $y ${m#0} ${d#0})"
+
+ # leap year
+ if [ "$m" -eq 2 -a "$d" -eq 29 ]; then
+ if [ "$((y % 400))" -eq 0 ]; then
+ :
+ elif [ "$((y % 100))" -eq 0 ]; then
+ return 1
+ elif [ "$((y % 4))" -eq 0 ]; then
+ :
+ else
+ return 1
+ fi
+ fi
+
+ printf '%04i-%02i-%02i\n' "$y" "${m#0}" "${d#0}"
+ return 0
+}
+
+istime(){
+ time="$1" h= m=
+
+ if printf %s "$time" | grep -xEq '(0?[1-9]|1[012])(:[0-5][0-9])? ?(am|AM)\.?'; then
+ time="${time%?[aA][mM]}" h="${time%:*}" h="$(h % 12)"
+ [ "$h" != "$time" ] && m="${time#*:}" || m=0
+ elif printf %s "$time" | grep -xEq '(0?[1-9]|1[012])(:[0-5][0-9])? ?(pm|PM)\.?'; then
+ time="${time%?[aA][mM]}" h="${time%:*}" h="$(h % 12 + 12)"
+ [ "$h" != "$time" ] && m="${time#*:}" || m=0
+ elif printf %s "$time" | grep -xEq '(0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]'; then
+ time="${time%?[aA][mM]}" h="${time%:*}" m="${time#*:}"
+ else
+ return 1
+ fi
+
+ printf '%02i:%02i\n' "${h#0}" "${m#0}"
+ return 0
+}