-
-
Notifications
You must be signed in to change notification settings - Fork 51
Expand file tree
/
Copy pathclock.sh
More file actions
162 lines (146 loc) · 4.52 KB
/
Copy pathclock.sh
File metadata and controls
162 lines (146 loc) · 4.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/env bash
_BASHUNIT_CLOCK_NOW_IMPL=""
function bashunit::clock::_choose_impl() {
local shell_time
# Use explicit indices for Bash 3.0 compatibility (empty array access fails with set -u)
local attempts_count=0
local attempts
# 1. Try native shell EPOCHREALTIME (fastest - no subprocess, Bash 5.0+)
attempts[attempts_count]="EPOCHREALTIME"
attempts_count=$((attempts_count + 1))
if shell_time="$(bashunit::clock::shell_time)"; then
_BASHUNIT_CLOCK_NOW_IMPL="shell"
return 0
fi
# 2. Unix date +%s%N (no subprocess overhead on supported systems)
attempts[attempts_count]="date"
attempts_count=$((attempts_count + 1))
if ! bashunit::check_os::is_macos && ! bashunit::check_os::is_alpine; then
local result
result=$(date +%s%N 2>/dev/null)
if [ "$(echo "$result" | "$GREP" -cv 'N' || true)" -gt 0 ] \
&& [ "$(echo "$result" | "$GREP" -cE '^[0-9]+$' || true)" -gt 0 ]; then
_BASHUNIT_CLOCK_NOW_IMPL="date"
return 0
fi
fi
# 3. Try Perl with Time::HiRes
attempts[attempts_count]="Perl"
attempts_count=$((attempts_count + 1))
if bashunit::dependencies::has_perl && perl -MTime::HiRes -e "" &>/dev/null; then
_BASHUNIT_CLOCK_NOW_IMPL="perl"
return 0
fi
# 4. Try Python 3 with time module
attempts[attempts_count]="Python"
attempts_count=$((attempts_count + 1))
if bashunit::dependencies::has_python; then
_BASHUNIT_CLOCK_NOW_IMPL="python"
return 0
fi
# 5. Try Node.js
attempts[attempts_count]="Node"
attempts_count=$((attempts_count + 1))
if bashunit::dependencies::has_node; then
_BASHUNIT_CLOCK_NOW_IMPL="node"
return 0
fi
# 6. Windows fallback with PowerShell
attempts[attempts_count]="PowerShell"
attempts_count=$((attempts_count + 1))
if bashunit::check_os::is_windows && bashunit::dependencies::has_powershell; then
_BASHUNIT_CLOCK_NOW_IMPL="powershell"
return 0
fi
# 7. Very last fallback: seconds resolution only
attempts[attempts_count]="date-seconds"
attempts_count=$((attempts_count + 1))
if date +%s &>/dev/null; then
_BASHUNIT_CLOCK_NOW_IMPL="date-seconds"
return 0
fi
# 8. All methods failed
printf "bashunit::clock::now implementations tried: %s\n" "${attempts[*]}" >&2
echo ""
return 1
}
function bashunit::clock::now() {
if [ -z "$_BASHUNIT_CLOCK_NOW_IMPL" ]; then
bashunit::clock::_choose_impl || return 1
fi
case "$_BASHUNIT_CLOCK_NOW_IMPL" in
perl)
perl -MTime::HiRes -e 'printf("%.0f\n", Time::HiRes::time() * 1000000000)'
;;
python)
python - <<'EOF'
import time, sys
sys.stdout.write(str(int(time.time() * 1000000000)))
EOF
;;
node)
node -e 'process.stdout.write((BigInt(Date.now()) * 1000000n).toString())'
;;
powershell)
powershell -Command "\
\$unixEpoch = [DateTime]'1970-01-01 00:00:00';\
\$now = [DateTime]::UtcNow;\
\$ticksSinceEpoch = (\$now - \$unixEpoch).Ticks;\
\$nanosecondsSinceEpoch = \$ticksSinceEpoch * 100;\
Write-Output \$nanosecondsSinceEpoch\
"
;;
date)
date +%s%N
;;
date-seconds)
local seconds
seconds=$(date +%s)
echo "$((seconds * 1000000000))"
;;
shell)
# shellcheck disable=SC2155
local shell_time="$(bashunit::clock::shell_time)"
local seconds="${shell_time%%[.,]*}"
local microseconds="${shell_time#*[.,]}"
if [ "$seconds" = "$shell_time" ]; then
microseconds=""
fi
# Pad to 6 digits and strip leading zeros for arithmetic
microseconds="${microseconds}000000"
microseconds="${microseconds:0:6}"
microseconds="${microseconds#"${microseconds%%[!0]*}"}"
microseconds="${microseconds:-0}"
echo "$(( (seconds * 1000000000) + (microseconds * 1000) ))"
;;
*)
bashunit::clock::_choose_impl || return 1
bashunit::clock::now
;;
esac
}
function bashunit::clock::shell_time() {
# Get time directly from the shell variable EPOCHREALTIME (Bash 5+)
[ -n "${EPOCHREALTIME+x}" ] && [ -n "$EPOCHREALTIME" ] && LC_ALL=C echo "$EPOCHREALTIME"
}
function bashunit::clock::total_runtime_in_milliseconds() {
local end_time
end_time=$(bashunit::clock::now)
if [ -n "$end_time" ]; then
bashunit::math::calculate "($end_time - $_BASHUNIT_START_TIME) / 1000000"
else
echo ""
fi
}
function bashunit::clock::total_runtime_in_nanoseconds() {
local end_time
end_time=$(bashunit::clock::now)
if [ -n "$end_time" ]; then
bashunit::math::calculate "$end_time - $_BASHUNIT_START_TIME"
else
echo ""
fi
}
function bashunit::clock::init() {
_BASHUNIT_START_TIME=$(bashunit::clock::now)
}