diff --git a/CHANGELOG b/CHANGELOG
index 4f4ce305..711d41f8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -5,6 +5,7 @@ jc changelog
- Add Email Address string parser
- Add JWT string parser
- Add ISO 8601 Datetime string parser
+- Add UNIX Epoch Timestamp string parser
- Add m3u/m3u8 file parser
- Add pager functionality to help (parser documentation only)
- Minor parser performance optimizations
diff --git a/EXAMPLES.md b/EXAMPLES.md
index 1edd73ce..2bf236ab 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -3599,6 +3599,47 @@ timedatectl | jc --timedatectl -p # or: jc -p timedatectl
"epoch_utc": 1583888001
}
```
+### Timestamp strings (UNIX Epoch)
+```bash
+echo '1658599410' | jc --timestamp -p
+```
+```json
+{
+ "naive": {
+ "year": 2022,
+ "month": "Jul",
+ "month_num": 7,
+ "day": 23,
+ "weekday": "Sat",
+ "weekday_num": 6,
+ "hour": 11,
+ "hour_24": 11,
+ "minute": 3,
+ "second": 30,
+ "period": "AM",
+ "day_of_year": 204,
+ "week_of_year": 29,
+ "iso": "2022-07-23T11:03:30"
+ },
+ "utc": {
+ "year": 2022,
+ "month": "Jul",
+ "month_num": 7,
+ "day": 23,
+ "weekday": "Sat",
+ "weekday_num": 6,
+ "hour": 6,
+ "hour_24": 18,
+ "minute": 3,
+ "second": 30,
+ "period": "PM",
+ "utc_offset": "+0000",
+ "day_of_year": 204,
+ "week_of_year": 29,
+ "iso": "2022-07-23T18:03:30+00:00"
+ }
+}
+```
### tob -b
```bash
top -b -n 1 | jc --top -p # or jc -p tob -b -n 1
diff --git a/README.md b/README.md
index 75ff2205..07d29f9a 100644
--- a/README.md
+++ b/README.md
@@ -236,6 +236,7 @@ option.
| ` --systeminfo` | `systeminfo` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systeminfo) |
| ` --time` | `/usr/bin/time` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/time) |
| ` --timedatectl` | `timedatectl status` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timedatectl) |
+| ` --timestamp` | UNIX Epoch Timestamp string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timestamp) |
| ` --top` | `top -b` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top) |
| ` --top-s` | `top -b` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top_s) |
| ` --tracepath` | `tracepath` and `tracepath6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath) |
diff --git a/completions/jc_bash_completion.sh b/completions/jc_bash_completion.sh
index 408df6c8..6df9299d 100644
--- a/completions/jc_bash_completion.sh
+++ b/completions/jc_bash_completion.sh
@@ -4,7 +4,7 @@ _jc()
jc_about_options jc_about_mod_options jc_help_options jc_special_options
jc_commands=(acpi airport arp blkid chage cksum crontab date df dig dmidecode dpkg du env file finger free git gpg hciconfig id ifconfig iostat iptables iw jobs last lastb ls lsblk lsmod lsof lsusb md5 md5sum mount mpstat netstat nmcli ntpq pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
- jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --chage --cksum --crontab --crontab-u --csv --csv-s --date --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --finger --free --fstab --git-log --git-log-s --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --iptables --iso-datetime --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lsusb --m3u --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --passwd --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --postconf --ps --route --rpm-qi --rsync --rsync-s --sfdisk --shadow --ss --stat --stat-s --sysctl --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --top --top-s --tracepath --traceroute --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
+ jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --chage --cksum --crontab --crontab-u --csv --csv-s --date --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --finger --free --fstab --git-log --git-log-s --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --iptables --iso-datetime --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lsusb --m3u --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --passwd --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --postconf --ps --route --rpm-qi --rsync --rsync-s --sfdisk --shadow --ss --stat --stat-s --sysctl --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --top --top-s --tracepath --traceroute --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_options=(--force-color -C --debug -d --monochrome -m --pretty -p --quiet -q --raw -r --unbuffer -u --yaml-out -y)
jc_about_options=(--about -a)
jc_about_mod_options=(--pretty -p --yaml-out -y --monochrome -m --force-color -C)
diff --git a/completions/jc_zsh_completion.sh b/completions/jc_zsh_completion.sh
index 4bff1c58..93f27005 100644
--- a/completions/jc_zsh_completion.sh
+++ b/completions/jc_zsh_completion.sh
@@ -94,7 +94,7 @@ _jc() {
'xrandr:run "xrandr" command with magic syntax.'
'zipinfo:run "zipinfo" command with magic syntax.'
)
- jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --chage --cksum --crontab --crontab-u --csv --csv-s --date --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --finger --free --fstab --git-log --git-log-s --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --iptables --iso-datetime --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lsusb --m3u --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --passwd --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --postconf --ps --route --rpm-qi --rsync --rsync-s --sfdisk --shadow --ss --stat --stat-s --sysctl --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --top --top-s --tracepath --traceroute --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
+ jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --chage --cksum --crontab --crontab-u --csv --csv-s --date --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --finger --free --fstab --git-log --git-log-s --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --iptables --iso-datetime --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lsusb --m3u --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --passwd --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --postconf --ps --route --rpm-qi --rsync --rsync-s --sfdisk --shadow --ss --stat --stat-s --sysctl --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --top --top-s --tracepath --traceroute --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_parsers_describe=(
'--acpi:`acpi` command parser'
'--airport:`airport -I` command parser'
@@ -184,6 +184,7 @@ _jc() {
'--systeminfo:`systeminfo` command parser'
'--time:`/usr/bin/time` command parser'
'--timedatectl:`timedatectl status` command parser'
+ '--timestamp:UNIX Epoch Timestamp string parser'
'--top:`top -b` command parser'
'--top-s:`top -b` command streaming parser'
'--tracepath:`tracepath` and `tracepath6` command parser'
diff --git a/docs/parsers/timestamp.md b/docs/parsers/timestamp.md
new file mode 100644
index 00000000..9706a1bd
--- /dev/null
+++ b/docs/parsers/timestamp.md
@@ -0,0 +1,122 @@
+[Home](https://kellyjonbrazil.github.io/jc/)
+
+
+# jc.parsers.timestamp
+
+jc - JSON Convert UNIX Epoch Timestamp string parser
+
+The naive fields are based on the local time of the system the parser is
+run on.
+
+The utc fields are timezone-aware, based on the UTC timezone.
+
+Usage (cli):
+
+ $ echo "2022-07-20T14:52:45Z" | jc --timestamp
+
+Usage (module):
+
+ import jc
+ result = jc.parse('timestamp', timestamp_string)
+
+Schema:
+
+ {
+ "naive": {
+ "year": integer,
+ "month": string,
+ "month_num": integer,
+ "day": integer,
+ "weekday": string,
+ "weekday_num": integer,
+ "hour": integer,
+ "hour_24": integer,
+ "minute": integer,
+ "second": integer,
+ "period": string,
+ "day_of_year": integer,
+ "week_of_year": integer,
+ "iso": string
+ },
+ "utc": {
+ "year": integer,
+ "month": string,
+ "month_num": integer,
+ "day": integer,
+ "weekday": string,
+ "weekday_num": integer,
+ "hour": integer,
+ "hour_24": integer,
+ "minute": integer,
+ "second": integer,
+ "period": string,
+ "utc_offset": string,
+ "day_of_year": integer,
+ "week_of_year": integer,
+ "iso": string
+ }
+ }
+
+Examples:
+
+ $ echo '1658599410' | jc --timestamp -p
+ {
+ "naive": {
+ "year": 2022,
+ "month": "Jul",
+ "month_num": 7,
+ "day": 23,
+ "weekday": "Sat",
+ "weekday_num": 6,
+ "hour": 11,
+ "hour_24": 11,
+ "minute": 3,
+ "second": 30,
+ "period": "AM",
+ "day_of_year": 204,
+ "week_of_year": 29,
+ "iso": "2022-07-23T11:03:30"
+ },
+ "utc": {
+ "year": 2022,
+ "month": "Jul",
+ "month_num": 7,
+ "day": 23,
+ "weekday": "Sat",
+ "weekday_num": 6,
+ "hour": 6,
+ "hour_24": 18,
+ "minute": 3,
+ "second": 30,
+ "period": "PM",
+ "utc_offset": "+0000",
+ "day_of_year": 204,
+ "week_of_year": 29,
+ "iso": "2022-07-23T18:03:30+00:00"
+ }
+ }
+
+
+
+### parse
+
+```python
+def parse(data, raw=False, quiet=False)
+```
+
+Main text parsing function
+
+Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+Returns:
+
+ Dictionary. Raw or processed structured data.
+
+### Parser Information
+Compatibility: linux, aix, freebsd, darwin, win32, cygwin
+
+Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/jc/lib.py b/jc/lib.py
index 9e254934..e17dfc06 100644
--- a/jc/lib.py
+++ b/jc/lib.py
@@ -97,6 +97,7 @@ parsers = [
'systeminfo',
'time',
'timedatectl',
+ 'timestamp',
'top',
'top-s',
'tracepath',
diff --git a/jc/parsers/timestamp.py b/jc/parsers/timestamp.py
new file mode 100644
index 00000000..d271527f
--- /dev/null
+++ b/jc/parsers/timestamp.py
@@ -0,0 +1,187 @@
+"""jc - JSON Convert UNIX Epoch Timestamp string parser
+
+The naive fields are based on the local time of the system the parser is
+run on.
+
+The utc fields are timezone-aware, based on the UTC timezone.
+
+Usage (cli):
+
+ $ echo "2022-07-20T14:52:45Z" | jc --timestamp
+
+Usage (module):
+
+ import jc
+ result = jc.parse('timestamp', timestamp_string)
+
+Schema:
+
+ {
+ "naive": {
+ "year": integer,
+ "month": string,
+ "month_num": integer,
+ "day": integer,
+ "weekday": string,
+ "weekday_num": integer,
+ "hour": integer,
+ "hour_24": integer,
+ "minute": integer,
+ "second": integer,
+ "period": string,
+ "day_of_year": integer,
+ "week_of_year": integer,
+ "iso": string
+ },
+ "utc": {
+ "year": integer,
+ "month": string,
+ "month_num": integer,
+ "day": integer,
+ "weekday": string,
+ "weekday_num": integer,
+ "hour": integer,
+ "hour_24": integer,
+ "minute": integer,
+ "second": integer,
+ "period": string,
+ "utc_offset": string,
+ "day_of_year": integer,
+ "week_of_year": integer,
+ "iso": string
+ }
+ }
+
+Examples:
+
+ $ echo '1658599410' | jc --timestamp -p
+ {
+ "naive": {
+ "year": 2022,
+ "month": "Jul",
+ "month_num": 7,
+ "day": 23,
+ "weekday": "Sat",
+ "weekday_num": 6,
+ "hour": 11,
+ "hour_24": 11,
+ "minute": 3,
+ "second": 30,
+ "period": "AM",
+ "day_of_year": 204,
+ "week_of_year": 29,
+ "iso": "2022-07-23T11:03:30"
+ },
+ "utc": {
+ "year": 2022,
+ "month": "Jul",
+ "month_num": 7,
+ "day": 23,
+ "weekday": "Sat",
+ "weekday_num": 6,
+ "hour": 6,
+ "hour_24": 18,
+ "minute": 3,
+ "second": 30,
+ "period": "PM",
+ "utc_offset": "+0000",
+ "day_of_year": 204,
+ "week_of_year": 29,
+ "iso": "2022-07-23T18:03:30+00:00"
+ }
+ }
+"""
+from datetime import datetime, timezone
+import jc.utils
+
+
+class info():
+ """Provides parser metadata (version, author, etc.)"""
+ version = '1.0'
+ description = 'UNIX Epoch Timestamp string parser'
+ author = 'Kelly Brazil'
+ author_email = 'kellyjonbrazil@gmail.com'
+ compatible = ['linux', 'aix', 'freebsd', 'darwin', 'win32', 'cygwin']
+
+
+__version__ = info.version
+
+
+def _process(proc_data):
+ """
+ Final processing to conform to the schema.
+
+ Parameters:
+
+ proc_data: (Dictionary) raw structured data to process
+
+ Returns:
+
+ Dictionary. Structured data to conform to the schema.
+ """
+ # no further processing
+ return proc_data
+
+
+def parse(data, raw=False, quiet=False):
+ """
+ Main text parsing function
+
+ Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+ Returns:
+
+ Dictionary. Raw or processed structured data.
+ """
+ jc.utils.compatibility(__name__, info.compatible, quiet)
+ jc.utils.input_type_check(data)
+
+ raw_output = {}
+
+ if jc.utils.has_data(data):
+
+ data = data[0:10]
+ dt = datetime.fromtimestamp(int(data))
+ dt_utc = datetime.fromtimestamp(int(data), tz=timezone.utc)
+
+ raw_output = {
+ 'naive': {
+ 'year': dt.year,
+ 'month': dt.strftime('%b'),
+ 'month_num': dt.month,
+ 'day': dt.day,
+ 'weekday': dt.strftime('%a'),
+ 'weekday_num': dt.isoweekday(),
+ 'hour': int(dt.strftime('%I')),
+ 'hour_24': dt.hour,
+ 'minute': dt.minute,
+ 'second': dt.second,
+ 'period': dt.strftime('%p').upper(),
+ 'day_of_year': int(dt.strftime('%j')),
+ 'week_of_year': int(dt.strftime('%W')),
+ 'iso': dt.isoformat()
+ },
+ 'utc': {
+ 'year': dt_utc.year,
+ 'month': dt_utc.strftime('%b'),
+ 'month_num': dt_utc.month,
+ 'day': dt_utc.day,
+ 'weekday': dt_utc.strftime('%a'),
+ 'weekday_num': dt_utc.isoweekday(),
+ 'hour': int(dt_utc.strftime('%I')),
+ 'hour_24': dt_utc.hour,
+ 'minute': dt_utc.minute,
+ 'second': dt_utc.second,
+ 'period': dt_utc.strftime('%p').upper(),
+ 'utc_offset': dt_utc.strftime('%z') or None,
+ 'day_of_year': int(dt_utc.strftime('%j')),
+ 'week_of_year': int(dt_utc.strftime('%W')),
+ 'iso': dt_utc.isoformat()
+ }
+ }
+
+ return raw_output if raw else _process(raw_output)
diff --git a/man/jc.1 b/man/jc.1
index eca414e0..992c89d4 100644
--- a/man/jc.1
+++ b/man/jc.1
@@ -457,6 +457,11 @@ M3U and M3U8 file parser
\fB--timedatectl\fP
`timedatectl status` command parser
+.TP
+.B
+\fB--timestamp\fP
+UNIX Epoch Timestamp string parser
+
.TP
.B
\fB--top\fP