tslib 2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
tslib-2.0/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "{}"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright {yyyy} {name of copyright owner}
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
tslib-2.0/PKG-INFO ADDED
@@ -0,0 +1,258 @@
1
+ Metadata-Version: 2.4
2
+ Name: tslib
3
+ Version: 2.0
4
+ Summary: A library for dealing with human-readable time offsets and timestamps
5
+ Author-email: Maxime Petazzoni <maxime.petazzoni@bulix.org>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/mpetazzoni/tslib
8
+ Project-URL: Issues, https://github.com/mpetazzoni/tslib/issues
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Requires-Python: >=3.11
13
+ Description-Content-Type: text/x-rst
14
+ License-File: LICENSE
15
+ Requires-Dist: tzdata
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest>=8; extra == "dev"
18
+ Requires-Dist: ruff; extra == "dev"
19
+ Requires-Dist: build; extra == "dev"
20
+ Requires-Dist: twine; extra == "dev"
21
+ Dynamic: license-file
22
+
23
+ Timestamp library and utility
24
+ =============================
25
+
26
+ ``tslib`` is a timestamp processing toolkit and library, written in
27
+ Python. It is very helpful when dealing with the millisecond-precision
28
+ timestamps that we encounter all the time in computer systems, and to
29
+ work with human-readable time deltas away from "now".
30
+
31
+ Installation
32
+ ------------
33
+
34
+ You can install ``tslib`` directly from PyPI with the following command:
35
+
36
+ ::
37
+
38
+ $ pip install tslib
39
+
40
+ If you're installing from a clone of this repository, use:
41
+
42
+ ::
43
+
44
+ $ git clone https://github.com/mpetazzoni/tslib
45
+ $ cd tslib/
46
+ $ pip install -e .
47
+
48
+ ``tslib`` requires Python 3.11 or newer. Named timezones use Python's
49
+ ``zoneinfo`` module and the system IANA timezone database, with the
50
+ automatically installed ``tzdata`` package as a fallback. Neither ``pytz``
51
+ nor ``six`` is required.
52
+
53
+ You're now ready to use ``ts``, which should be directly available in
54
+ your ``$PATH``.
55
+
56
+ Usage
57
+ -----
58
+
59
+ ::
60
+
61
+ $ ts -h
62
+ usage: ts [-h] [-t TZ] [-n] [-i] [-a {minute,hour,day}]
63
+
64
+ Human readable timestamps
65
+
66
+ options:
67
+ -h, --help show this help message and exit
68
+ -t, --timezone TZ Use IANA timezone TZ (default: OS local timezone)
69
+ -n, --timestamp-only Only output the resulting millisecond timestamp(s)
70
+ -i, --inline Apply timestamp replacements inline of the incoming
71
+ text
72
+ -a, --align {minute,hour,day}
73
+ Align the timestamp
74
+
75
+ ``ts`` transforms milliseconds timestamps and human-readable deltas into
76
+ fully qualified date and time printouts, containing:
77
+
78
+ - the UTC timestamp (since Epoch)
79
+ - the UTC time represented by the timestamp
80
+ - the local time represented by the timestamp
81
+ - the human-readable delta of this timestamp against current time
82
+
83
+ The output is tab-delimited and can easily be re-segmented by piping
84
+ into ``column -t -s "\t"``.
85
+
86
+ Arguments can be passed as command-line arguments, or piped into ``ts``
87
+ via STDIN. If no input comes from either of these sources, ``ts`` will
88
+ simply output the current time:
89
+
90
+ ::
91
+
92
+ $ ts -t America/Los_Angeles
93
+ 1423599084206 2015-02-10 20:11:24.206 UTC+0000 2015-02-10 12:11:24.206 PST-0800 0
94
+
95
+ Inline mode
96
+ -----------
97
+
98
+ ``ts`` can operate in inline-replacement mode, for timestamps only. In
99
+ this mode, you can pipe in any text and ``ts`` will output it back to
100
+ you with all timestamps replaced with a human-readable date and time and
101
+ human-readable delta representation.
102
+
103
+ Given the inherent difficulty of accurately matching timestamps, the
104
+ matching is limited to 13-digits millisecond precision timestamps (that
105
+ may be immediately followed by a ``L``). Numbers smaller, or larger than
106
+ 13 digits are not matched, and are left alone; meaning no 13-digit
107
+ section of them is matched and replaced.
108
+
109
+ ::
110
+
111
+ $ echo B_b-3PAAYAA B_cJXlvAYAA B_cJXl6AcAA \
112
+ | xargs sfc mb g -p TSVH -f sf_checkpointTimestampMs -f sf_updatedOnMs \
113
+ | ts -i -t America/Los_Angeles \
114
+ | column -t -s " "
115
+ sf_id sf_checkpointTimestampMs sf_updatedOnMs
116
+ B_b-3PAAYAA 2015-03-06 13:38:58.851 PST-0800 (-2w5h18m6s210) 2015-03-06 13:38:58.852 PST-0800 (-2w5h18m6s209)
117
+ B_cJXlvAYAA 2015-03-08 09:04:36.218 PDT-0700 (-1w5d10h52m28s843) 2015-03-08 09:04:36.218 PDT-0700 (-1w5d10h52m28s844)
118
+ B_cJXl6AcAA 2015-03-08 09:04:34.252 PDT-0700 (-1w5d10h52m30s810) 2015-03-08 09:04:34.342 PDT-0700 (-1w5d10h52m30s720)
119
+
120
+ More examples
121
+ -------------
122
+
123
+ Piping:
124
+
125
+ ::
126
+
127
+ $ cat << EOF | ts -t America/Los_Angeles
128
+ pipe heredoc> 1404424797009L
129
+ pipe heredoc> 1415917836779L
130
+ pipe heredoc> EOF
131
+ 1404424797009 2014-07-03 21:59:57.009 UTC+0000 2014-07-03 14:59:57.009 PDT-0700 -31w5d1h14m26s38
132
+ 1415917836779 2014-11-13 22:30:36.779 UTC+0000 2014-11-13 14:30:36.779 PST-0800 -12w5d43m46s268
133
+
134
+ Using the column output (assuming the same input in a ``/tmp/ts.txt``
135
+ file):
136
+
137
+ ::
138
+
139
+ $ cat /tmp/ts.txt | ts | cut -f4
140
+ -31w5d1h16m17s703
141
+ -12w5d45m37s933
142
+
143
+ Sorting on a column (here, by descending timestamps in first column):
144
+
145
+ ::
146
+
147
+ $ cat /tmp/ts.txt | ts -t America/Los_Angeles | sort -k1 -t $'\t' -r
148
+ 1415917836779 2014-11-13 22:30:36.779 UTC+0000 2014-11-13 14:30:36.779 PST-0800 -12w5d46m6s924
149
+ 1404424797009 2014-07-03 21:59:57.009 UTC+0000 2014-07-03 14:59:57.009 PDT-0700 -31w5d1h16m46s694
150
+
151
+ Deltas
152
+ ------
153
+
154
+ Human-readable deltas can be expressed in weeks (``w``), days (``d``),
155
+ hours (``h``), minutes (``m``), and seconds (``s``). The remainder,
156
+ without a unit, is assumed to be milliseconds. Any "segment" can be
157
+ omitted, the only requirement is that the segments that are specified
158
+ are written in descending order of span (days before hours, hours before
159
+ minutes, etc.).
160
+
161
+ Here's an example: ``-12w4d6m57s257``. Note that *hours* are missing,
162
+ which simply means 12 weeks, 4 days, 6 minutes, 57 seconds and 257
163
+ milliseconds.
164
+
165
+ As you might have guessed, deltas can be both negative and positive. For
166
+ positive deltas, the leading ``+`` may be omitted if units are used,
167
+ otherwise the number is assumed to be an absolute timestamp:
168
+
169
+ ::
170
+
171
+ $ ts -t America/Los_Angeles -1
172
+ 1423599850752 2015-02-10 20:24:10.752 UTC+0000 2015-02-10 12:24:10.752 PST-0800 -1
173
+ $ ts -t America/Los_Angeles 0 1
174
+ 0 1970-01-01 00:00:00.000 UTC+0000 1969-12-31 16:00:00.000 PST-0800 -2353w5d20h24m14s145
175
+ 1 1970-01-01 00:00:00.001 UTC+0000 1969-12-31 16:00:00.001 PST-0800 -2353w5d20h24m14s144
176
+ $ ts -t America/Los_Angeles +1
177
+ 1423599855941 2015-02-10 20:24:15.941 UTC+0000 2015-02-10 12:24:15.941 PST-0800 1
178
+
179
+ Using a different local timezone
180
+ --------------------------------
181
+
182
+ The third column shows the timestamp's representation in local time. By
183
+ default it uses the operating system's configured local timezone, including
184
+ the daylight-saving offset appropriate to the timestamp being converted.
185
+ It does not depend on the legacy ``US/Pacific`` timezone alias. On POSIX
186
+ systems, the ``TZ`` environment variable can override the local timezone.
187
+
188
+ Use ``-t`` to select an explicit IANA timezone name, such as ``UTC``,
189
+ ``America/Los_Angeles``, or ``Europe/Paris``. Invalid names produce a
190
+ command-line usage error. The Pacific-time examples above explicitly select
191
+ ``America/Los_Angeles`` so their output does not depend on the host timezone:
192
+
193
+ ::
194
+
195
+ $ ts -t Europe/Paris
196
+ 1423600015955 2015-02-10 20:26:55.955 UTC+0000 2015-02-10 21:26:55.955 CET+0100 0
197
+
198
+ Absolute, human-readable offsets from Epoch
199
+ -------------------------------------------
200
+
201
+ By prefixing a human-readable delta with an equal sign (``=``), you
202
+ obtain an absolute offset from the Epoch. The side-effect of this is
203
+ that it allows for converting a human-readable delta into its
204
+ corresponding millisecond duration.
205
+
206
+ ::
207
+
208
+ $ ts -n '=1h'
209
+ 3600000
210
+ $ ts -t America/Los_Angeles '=1d'
211
+ 86400000 1970-01-02 00:00:00.000 UTC+0000 1970-01-01 16:00:00.000 PST-0800 -2365w6d21h56m20s98
212
+
213
+ Alignment
214
+ ---------
215
+
216
+ ``-a minute``, ``-a hour``, and ``-a day`` round forward to the next UTC
217
+ boundary, even if the timestamp is already aligned. The chosen display
218
+ timezone does not change the alignment:
219
+
220
+ ::
221
+
222
+ $ ts -n -a hour 1
223
+ 3600000
224
+
225
+ Library compatibility
226
+ ---------------------
227
+
228
+ UTC datetime helpers now return standard-library ``datetime`` objects with
229
+ ``datetime.timezone.utc`` rather than ``pytz.utc``. ``date_from_utc`` still
230
+ requires a naive datetime and rejects an already timezone-aware value.
231
+ Replace ``pytz``-specific operations such as ``localize`` and ``normalize``
232
+ with standard-library datetime operations when upgrading.
233
+
234
+ ``render_date(date)`` keeps its UTC display default for library callers.
235
+ Pass ``None`` to use the OS-local timezone, or a ``zoneinfo.ZoneInfo`` object
236
+ to select a named timezone:
237
+
238
+ ::
239
+
240
+ from zoneinfo import ZoneInfo
241
+ from tslib import date_from_utc_ts, render_date
242
+
243
+ print(render_date(date_from_utc_ts(1404424797009), ZoneInfo("Europe/Paris")))
244
+
245
+ Development
246
+ -----------
247
+
248
+ Install the development dependencies in a virtual environment, then run:
249
+
250
+ ::
251
+
252
+ $ python -m pip install -e '.[dev]'
253
+ $ python -m pytest
254
+ $ python -m ruff check .
255
+ $ python -m build
256
+ $ python -m twine check dist/*
257
+
258
+ CI runs these checks on Python 3.11 through 3.14 on Linux, macOS, and Windows.
tslib-2.0/README.rst ADDED
@@ -0,0 +1,236 @@
1
+ Timestamp library and utility
2
+ =============================
3
+
4
+ ``tslib`` is a timestamp processing toolkit and library, written in
5
+ Python. It is very helpful when dealing with the millisecond-precision
6
+ timestamps that we encounter all the time in computer systems, and to
7
+ work with human-readable time deltas away from "now".
8
+
9
+ Installation
10
+ ------------
11
+
12
+ You can install ``tslib`` directly from PyPI with the following command:
13
+
14
+ ::
15
+
16
+ $ pip install tslib
17
+
18
+ If you're installing from a clone of this repository, use:
19
+
20
+ ::
21
+
22
+ $ git clone https://github.com/mpetazzoni/tslib
23
+ $ cd tslib/
24
+ $ pip install -e .
25
+
26
+ ``tslib`` requires Python 3.11 or newer. Named timezones use Python's
27
+ ``zoneinfo`` module and the system IANA timezone database, with the
28
+ automatically installed ``tzdata`` package as a fallback. Neither ``pytz``
29
+ nor ``six`` is required.
30
+
31
+ You're now ready to use ``ts``, which should be directly available in
32
+ your ``$PATH``.
33
+
34
+ Usage
35
+ -----
36
+
37
+ ::
38
+
39
+ $ ts -h
40
+ usage: ts [-h] [-t TZ] [-n] [-i] [-a {minute,hour,day}]
41
+
42
+ Human readable timestamps
43
+
44
+ options:
45
+ -h, --help show this help message and exit
46
+ -t, --timezone TZ Use IANA timezone TZ (default: OS local timezone)
47
+ -n, --timestamp-only Only output the resulting millisecond timestamp(s)
48
+ -i, --inline Apply timestamp replacements inline of the incoming
49
+ text
50
+ -a, --align {minute,hour,day}
51
+ Align the timestamp
52
+
53
+ ``ts`` transforms milliseconds timestamps and human-readable deltas into
54
+ fully qualified date and time printouts, containing:
55
+
56
+ - the UTC timestamp (since Epoch)
57
+ - the UTC time represented by the timestamp
58
+ - the local time represented by the timestamp
59
+ - the human-readable delta of this timestamp against current time
60
+
61
+ The output is tab-delimited and can easily be re-segmented by piping
62
+ into ``column -t -s "\t"``.
63
+
64
+ Arguments can be passed as command-line arguments, or piped into ``ts``
65
+ via STDIN. If no input comes from either of these sources, ``ts`` will
66
+ simply output the current time:
67
+
68
+ ::
69
+
70
+ $ ts -t America/Los_Angeles
71
+ 1423599084206 2015-02-10 20:11:24.206 UTC+0000 2015-02-10 12:11:24.206 PST-0800 0
72
+
73
+ Inline mode
74
+ -----------
75
+
76
+ ``ts`` can operate in inline-replacement mode, for timestamps only. In
77
+ this mode, you can pipe in any text and ``ts`` will output it back to
78
+ you with all timestamps replaced with a human-readable date and time and
79
+ human-readable delta representation.
80
+
81
+ Given the inherent difficulty of accurately matching timestamps, the
82
+ matching is limited to 13-digits millisecond precision timestamps (that
83
+ may be immediately followed by a ``L``). Numbers smaller, or larger than
84
+ 13 digits are not matched, and are left alone; meaning no 13-digit
85
+ section of them is matched and replaced.
86
+
87
+ ::
88
+
89
+ $ echo B_b-3PAAYAA B_cJXlvAYAA B_cJXl6AcAA \
90
+ | xargs sfc mb g -p TSVH -f sf_checkpointTimestampMs -f sf_updatedOnMs \
91
+ | ts -i -t America/Los_Angeles \
92
+ | column -t -s " "
93
+ sf_id sf_checkpointTimestampMs sf_updatedOnMs
94
+ B_b-3PAAYAA 2015-03-06 13:38:58.851 PST-0800 (-2w5h18m6s210) 2015-03-06 13:38:58.852 PST-0800 (-2w5h18m6s209)
95
+ B_cJXlvAYAA 2015-03-08 09:04:36.218 PDT-0700 (-1w5d10h52m28s843) 2015-03-08 09:04:36.218 PDT-0700 (-1w5d10h52m28s844)
96
+ B_cJXl6AcAA 2015-03-08 09:04:34.252 PDT-0700 (-1w5d10h52m30s810) 2015-03-08 09:04:34.342 PDT-0700 (-1w5d10h52m30s720)
97
+
98
+ More examples
99
+ -------------
100
+
101
+ Piping:
102
+
103
+ ::
104
+
105
+ $ cat << EOF | ts -t America/Los_Angeles
106
+ pipe heredoc> 1404424797009L
107
+ pipe heredoc> 1415917836779L
108
+ pipe heredoc> EOF
109
+ 1404424797009 2014-07-03 21:59:57.009 UTC+0000 2014-07-03 14:59:57.009 PDT-0700 -31w5d1h14m26s38
110
+ 1415917836779 2014-11-13 22:30:36.779 UTC+0000 2014-11-13 14:30:36.779 PST-0800 -12w5d43m46s268
111
+
112
+ Using the column output (assuming the same input in a ``/tmp/ts.txt``
113
+ file):
114
+
115
+ ::
116
+
117
+ $ cat /tmp/ts.txt | ts | cut -f4
118
+ -31w5d1h16m17s703
119
+ -12w5d45m37s933
120
+
121
+ Sorting on a column (here, by descending timestamps in first column):
122
+
123
+ ::
124
+
125
+ $ cat /tmp/ts.txt | ts -t America/Los_Angeles | sort -k1 -t $'\t' -r
126
+ 1415917836779 2014-11-13 22:30:36.779 UTC+0000 2014-11-13 14:30:36.779 PST-0800 -12w5d46m6s924
127
+ 1404424797009 2014-07-03 21:59:57.009 UTC+0000 2014-07-03 14:59:57.009 PDT-0700 -31w5d1h16m46s694
128
+
129
+ Deltas
130
+ ------
131
+
132
+ Human-readable deltas can be expressed in weeks (``w``), days (``d``),
133
+ hours (``h``), minutes (``m``), and seconds (``s``). The remainder,
134
+ without a unit, is assumed to be milliseconds. Any "segment" can be
135
+ omitted, the only requirement is that the segments that are specified
136
+ are written in descending order of span (days before hours, hours before
137
+ minutes, etc.).
138
+
139
+ Here's an example: ``-12w4d6m57s257``. Note that *hours* are missing,
140
+ which simply means 12 weeks, 4 days, 6 minutes, 57 seconds and 257
141
+ milliseconds.
142
+
143
+ As you might have guessed, deltas can be both negative and positive. For
144
+ positive deltas, the leading ``+`` may be omitted if units are used,
145
+ otherwise the number is assumed to be an absolute timestamp:
146
+
147
+ ::
148
+
149
+ $ ts -t America/Los_Angeles -1
150
+ 1423599850752 2015-02-10 20:24:10.752 UTC+0000 2015-02-10 12:24:10.752 PST-0800 -1
151
+ $ ts -t America/Los_Angeles 0 1
152
+ 0 1970-01-01 00:00:00.000 UTC+0000 1969-12-31 16:00:00.000 PST-0800 -2353w5d20h24m14s145
153
+ 1 1970-01-01 00:00:00.001 UTC+0000 1969-12-31 16:00:00.001 PST-0800 -2353w5d20h24m14s144
154
+ $ ts -t America/Los_Angeles +1
155
+ 1423599855941 2015-02-10 20:24:15.941 UTC+0000 2015-02-10 12:24:15.941 PST-0800 1
156
+
157
+ Using a different local timezone
158
+ --------------------------------
159
+
160
+ The third column shows the timestamp's representation in local time. By
161
+ default it uses the operating system's configured local timezone, including
162
+ the daylight-saving offset appropriate to the timestamp being converted.
163
+ It does not depend on the legacy ``US/Pacific`` timezone alias. On POSIX
164
+ systems, the ``TZ`` environment variable can override the local timezone.
165
+
166
+ Use ``-t`` to select an explicit IANA timezone name, such as ``UTC``,
167
+ ``America/Los_Angeles``, or ``Europe/Paris``. Invalid names produce a
168
+ command-line usage error. The Pacific-time examples above explicitly select
169
+ ``America/Los_Angeles`` so their output does not depend on the host timezone:
170
+
171
+ ::
172
+
173
+ $ ts -t Europe/Paris
174
+ 1423600015955 2015-02-10 20:26:55.955 UTC+0000 2015-02-10 21:26:55.955 CET+0100 0
175
+
176
+ Absolute, human-readable offsets from Epoch
177
+ -------------------------------------------
178
+
179
+ By prefixing a human-readable delta with an equal sign (``=``), you
180
+ obtain an absolute offset from the Epoch. The side-effect of this is
181
+ that it allows for converting a human-readable delta into its
182
+ corresponding millisecond duration.
183
+
184
+ ::
185
+
186
+ $ ts -n '=1h'
187
+ 3600000
188
+ $ ts -t America/Los_Angeles '=1d'
189
+ 86400000 1970-01-02 00:00:00.000 UTC+0000 1970-01-01 16:00:00.000 PST-0800 -2365w6d21h56m20s98
190
+
191
+ Alignment
192
+ ---------
193
+
194
+ ``-a minute``, ``-a hour``, and ``-a day`` round forward to the next UTC
195
+ boundary, even if the timestamp is already aligned. The chosen display
196
+ timezone does not change the alignment:
197
+
198
+ ::
199
+
200
+ $ ts -n -a hour 1
201
+ 3600000
202
+
203
+ Library compatibility
204
+ ---------------------
205
+
206
+ UTC datetime helpers now return standard-library ``datetime`` objects with
207
+ ``datetime.timezone.utc`` rather than ``pytz.utc``. ``date_from_utc`` still
208
+ requires a naive datetime and rejects an already timezone-aware value.
209
+ Replace ``pytz``-specific operations such as ``localize`` and ``normalize``
210
+ with standard-library datetime operations when upgrading.
211
+
212
+ ``render_date(date)`` keeps its UTC display default for library callers.
213
+ Pass ``None`` to use the OS-local timezone, or a ``zoneinfo.ZoneInfo`` object
214
+ to select a named timezone:
215
+
216
+ ::
217
+
218
+ from zoneinfo import ZoneInfo
219
+ from tslib import date_from_utc_ts, render_date
220
+
221
+ print(render_date(date_from_utc_ts(1404424797009), ZoneInfo("Europe/Paris")))
222
+
223
+ Development
224
+ -----------
225
+
226
+ Install the development dependencies in a virtual environment, then run:
227
+
228
+ ::
229
+
230
+ $ python -m pip install -e '.[dev]'
231
+ $ python -m pytest
232
+ $ python -m ruff check .
233
+ $ python -m build
234
+ $ python -m twine check dist/*
235
+
236
+ CI runs these checks on Python 3.11 through 3.14 on Linux, macOS, and Windows.