mirror of https://github.com/borgbackup/borg.git
always use microseconds for ISO 8601 output
(cherry picked from commit ab4981eff6
)
This commit is contained in:
parent
008571228f
commit
d5697fb4a8
|
@ -209,9 +209,9 @@ Standard output
|
|||
*stdout* is different and more command-dependent than logging. Commands like :ref:`borg_info`, :ref:`borg_create`
|
||||
and :ref:`borg_list` implement a ``--json`` option which turns their regular output into a single JSON object.
|
||||
|
||||
Dates are formatted according to ISO-8601 in local time. Neither an explicit time zone nor microseconds
|
||||
are specified *at this time* (subject to change). The equivalent strftime format string is '%Y-%m-%dT%H:%M:%S',
|
||||
e.g. 2017-08-07T12:27:20.
|
||||
Dates are formatted according to ISO 8601 in local time. No explicit time zone is specified *at this time*
|
||||
(subject to change). The equivalent strftime format string is '%Y-%m-%dT%H:%M:%S.%f',
|
||||
e.g. ``2017-08-07T12:27:20.123456``.
|
||||
|
||||
The root object at least contains a *repository* key with an object containing:
|
||||
|
||||
|
@ -268,7 +268,7 @@ Example *borg info* output::
|
|||
},
|
||||
"repository": {
|
||||
"id": "0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
|
||||
"last_modified": "2017-08-07T12:27:20",
|
||||
"last_modified": "2017-08-07T12:27:20.789123",
|
||||
"location": "/home/user/testrepo"
|
||||
},
|
||||
"security_dir": "/home/user/.config/borg/security/0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
|
||||
|
@ -329,7 +329,7 @@ Example of a simple archive listing (``borg list --last 1 --json``)::
|
|||
{
|
||||
"id": "80cd07219ad725b3c5f665c1dcf119435c4dee1647a560ecac30f8d40221a46a",
|
||||
"name": "host-system-backup-2017-02-27",
|
||||
"start": "2017-08-07T12:27:20"
|
||||
"start": "2017-08-07T12:27:20.789123"
|
||||
}
|
||||
],
|
||||
"encryption": {
|
||||
|
@ -337,7 +337,7 @@ Example of a simple archive listing (``borg list --last 1 --json``)::
|
|||
},
|
||||
"repository": {
|
||||
"id": "0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
|
||||
"last_modified": "2017-08-07T12:27:20",
|
||||
"last_modified": "2017-08-07T12:27:20.789123",
|
||||
"location": "/home/user/repository"
|
||||
}
|
||||
}
|
||||
|
@ -355,14 +355,14 @@ The same archive with more information (``borg info --last 1 --json``)::
|
|||
],
|
||||
"comment": "",
|
||||
"duration": 5.641542,
|
||||
"end": "2017-02-27T12:27:20",
|
||||
"end": "2017-02-27T12:27:20.789123",
|
||||
"hostname": "host",
|
||||
"id": "80cd07219ad725b3c5f665c1dcf119435c4dee1647a560ecac30f8d40221a46a",
|
||||
"limits": {
|
||||
"max_archive_size": 0.0001330855110409714
|
||||
},
|
||||
"name": "host-system-backup-2017-02-27",
|
||||
"start": "2017-02-27T12:27:20",
|
||||
"start": "2017-02-27T12:27:20.789123",
|
||||
"stats": {
|
||||
"compressed_size": 1880961894,
|
||||
"deduplicated_size": 2791,
|
||||
|
@ -388,7 +388,7 @@ The same archive with more information (``borg info --last 1 --json``)::
|
|||
},
|
||||
"repository": {
|
||||
"id": "0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
|
||||
"last_modified": "2017-08-07T12:27:20",
|
||||
"last_modified": "2017-08-07T12:27:20.789123",
|
||||
"location": "/home/user/repository"
|
||||
}
|
||||
}
|
||||
|
@ -406,8 +406,8 @@ Refer to the *borg list* documentation for the available keys and their meaning.
|
|||
|
||||
Example (excerpt) of ``borg list --json-lines``::
|
||||
|
||||
{"type": "d", "mode": "drwxr-xr-x", "user": "user", "group": "user", "uid": 1000, "gid": 1000, "path": "linux", "healthy": true, "source": "", "linktarget": "", "flags": null, "isomtime": "2017-02-27T12:27:20", "size": 0}
|
||||
{"type": "d", "mode": "drwxr-xr-x", "user": "user", "group": "user", "uid": 1000, "gid": 1000, "path": "linux/baz", "healthy": true, "source": "", "linktarget": "", "flags": null, "isomtime": "2017-02-27T12:27:20", "size": 0}
|
||||
{"type": "d", "mode": "drwxr-xr-x", "user": "user", "group": "user", "uid": 1000, "gid": 1000, "path": "linux", "healthy": true, "source": "", "linktarget": "", "flags": null, "mtime": "2017-02-27T12:27:20.023407", "size": 0}
|
||||
{"type": "d", "mode": "drwxr-xr-x", "user": "user", "group": "user", "uid": 1000, "gid": 1000, "path": "linux/baz", "healthy": true, "source": "", "linktarget": "", "flags": null, "mtime": "2017-02-27T12:27:20.585407", "size": 0}
|
||||
|
||||
.. _msgid:
|
||||
|
||||
|
|
|
@ -715,16 +715,19 @@ def safe_timestamp(item_timestamp_ns):
|
|||
return datetime.fromtimestamp(t_ns / 1e9)
|
||||
|
||||
|
||||
def format_time(t):
|
||||
"""use ISO-8601-like date and time format (human readable, with wkday and blank date/time separator)
|
||||
def format_time(ts: datetime):
|
||||
"""
|
||||
return t.strftime('%a, %Y-%m-%d %H:%M:%S')
|
||||
Convert *ts* to a human-friendly format with textual weekday.
|
||||
"""
|
||||
return ts.strftime('%a, %Y-%m-%d %H:%M:%S')
|
||||
|
||||
|
||||
def isoformat_time(t):
|
||||
"""use ISO-8601 date and time format (machine readable, no wkday, no microseconds either)
|
||||
def isoformat_time(ts: datetime):
|
||||
"""
|
||||
return t.strftime('%Y-%m-%dT%H:%M:%S') # note: first make all datetime objects tz aware before adding %z here.
|
||||
Format *ts* according to ISO 8601.
|
||||
"""
|
||||
# note: first make all datetime objects tz aware before adding %z here.
|
||||
return ts.strftime('%Y-%m-%dT%H:%M:%S.%f')
|
||||
|
||||
|
||||
def format_timedelta(td):
|
||||
|
@ -756,9 +759,11 @@ class OutputTimestamp:
|
|||
def __str__(self):
|
||||
return '{}'.format(self)
|
||||
|
||||
def to_json(self):
|
||||
def isoformat(self):
|
||||
return isoformat_time(self.ts)
|
||||
|
||||
to_json = isoformat
|
||||
|
||||
|
||||
def format_file_size(v, precision=2, sign=False):
|
||||
"""Format file size into a human friendly format
|
||||
|
@ -1895,7 +1900,7 @@ class ItemFormatter(BaseFormatter):
|
|||
return OutputTimestamp(safe_timestamp(item.get(key) or item.mtime))
|
||||
|
||||
def format_iso_time(self, key, item):
|
||||
return self.format_time(key, item).to_json()
|
||||
return self.format_time(key, item).isoformat()
|
||||
|
||||
|
||||
class ChunkIteratorFileWrapper:
|
||||
|
|
|
@ -60,7 +60,7 @@ from . import key
|
|||
|
||||
src_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
ISO_FORMAT = '%Y-%m-%dT%H:%M:%S'
|
||||
ISO_FORMAT = '%Y-%m-%dT%H:%M:%S.%f'
|
||||
|
||||
|
||||
def exec_cmd(*args, archiver=None, fork=False, exe=None, input=b'', binary_output=False, **kw):
|
||||
|
@ -1863,7 +1863,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
|
|||
file1 = items[1]
|
||||
assert file1['path'] == 'input/file1'
|
||||
assert file1['size'] == 81920
|
||||
assert datetime.strptime(file1['isomtime'], ISO_FORMAT) # must not raise
|
||||
assert datetime.strptime(file1['mtime'], ISO_FORMAT) # must not raise
|
||||
|
||||
list_archive = self.cmd('list', '--json-lines', '--format={sha256}', self.repository_location + '::test')
|
||||
items = [json.loads(s) for s in list_archive.splitlines()]
|
||||
|
|
Loading…
Reference in New Issue