Skip to content

Commit

Permalink
WIP2
Browse files Browse the repository at this point in the history
  • Loading branch information
oldratlee committed Jan 29, 2024
1 parent d7a8e2c commit 1341c30
Showing 1 changed file with 30 additions and 17 deletions.
47 changes: 30 additions & 17 deletions bin/uxt
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,18 @@ is_integer() {
[[ "$1" =~ ^-?[[:digit:]]+$ ]]
}

die() {
red_print "Error: $*" >&2
exit 1
}

usage() {
local -r exit_code=${1:-0}
(($# > 0)) && shift
local -r out=$(((exit_code != 0) + 1))

# NOTE: $'foo' is the escape sequence syntax of bash
local nl=$'\n' # new line
(($# > 0)) && red_print "$*$nl" >&"$out"
(($# > 0)) && red_print "$*"$'\n' >&"$out"

cat >&"$out" <<EOF
Usage: $PROG [OPTION] unix-time [unix-time...]
Expand Down Expand Up @@ -139,46 +143,51 @@ done

readonly args unit trim_decimal_tailing_0 no_tz

if [ ${#args[@]} = 0 ]; then
usage 1 'No argument provided!' >&2
fi

################################################################################
# biz logic
################################################################################

if [ ${#args[@]} = 0 ]; then
usage 1 'No argument provided!' >&2
fi
for a in "${args[@]}"; do
is_integer "$a" || {
usage 1 "argument $a is not integer!" >&2
}
is_integer "$a" || die "argument $a is not integer!"
done

print_date() {
local epoch=$1
local input=$1
local negative_sign=
if [[ $input == -* ]]; then
negative_sign=-
input=${input#-}
fi

# case 1: is unix time in second?
if [[ $unit = s ]]; then
local input_value=$epoch
local date_input=$input seconds=$input
local format_n=
else
local len=${#epoch}
local len=${#input}

# case 2: is unix time in millisecond?
if [[ $unit = ms ]]; then
if ((len > 3)); then
local seconds=${1:0:len-3} decimal=${epoch:len-3:3}
local seconds=${1:0:len-3} decimal=${input:len-3:3}
else
local seconds=0 decimal
printf -v decimal '%03d' "$epoch"
printf -v decimal '%03d' "$input"
fi
# case 3: auto detect by length
else
# for short integer(<= 10 digits), treat as second
if ((len <= 10)); then
local seconds=$epoch decimal=
local seconds=$input decimal=
# for long integer(> 10 digits), treat first 10 digits as second,
# and the rest as decimal(use almost 9 digits, aka nano second)
else
local seconds=${epoch:0:10} decimal=${epoch:10:9}
((len <= 19)) || die "too much digits treat(more than 19 digits) as a recent date(treat first 10-digits as seconds, reset at most 9 digits as decimal)"
local seconds=${input:0:10} decimal=${input:10:9}
fi
fi

Expand All @@ -191,13 +200,17 @@ print_date() {
done
fi

local input_value=$seconds${decimal:+.$decimal}
local date_input=$seconds${decimal:+.$decimal}
local format_n=${decimal:+.%${#decimal}N}
fi

local seconds_value=$negative_sign$seconds
((${#seconds} > 17 || (seconds_value >= -67768040609769944 && seconds_value <= 67768036191647999))) ||
die "argument $input(seconds: $seconds_value${decimal:+, decimal: .$decimal}) is out of range! seconds should be in range [-67768040609769944, 67768036191647999]."

local format_tz=' %z'
$no_tz && format_tz=
date -d "@$input_value" +"%Y-%m-%d %H:%M:%S$format_n$format_tz"
date -d "@$negative_sign$date_input" +"%Y-%m-%d %H:%M:%S$format_n$format_tz"
}

for a in "${args[@]}"; do
Expand Down

0 comments on commit 1341c30

Please sign in to comment.