Repository: borgbackup/borg

Issue:
Consider changing {utcnow} and {now} to a format without embedded space.
Maybe the separator could be '_' instead.

Why? Handling archives names with embedded spaces is annoying on the commandline. It just irks me every time i need to move back to add quotes.

---

:moneybag: [there is a bounty for this](https://www.bountysource.com/issues/37921249-consider-changing-utcnow-and-now-to-a-format-without-embedded-space)



Discussion:
Agreed. There's a standardized format for it w/o the space (the ISO format, 2016-12-13T14:15:16). 

![8601](https://imgs.xkcd.com/comics/iso_8601.png)

:)

Milestone = 1.1 because it's possibly breaking scripts...


Resolving patch:
diff --git a/src/borg/archiver.py b/src/borg/archiver.py
--- a/src/borg/archiver.py
+++ b/src/borg/archiver.py
@@ -1233,11 +1233,13 @@ def do_break_lock(self, args, repository):
 
         {now}
 
-            The current local date and time.
+            The current local date and time, by default in ISO-8601 format.
+            You can also supply your own `format string <https://docs.python.org/3.4/library/datetime.html#strftime-and-strptime-behavior>`_, e.g. {now:%Y-%m-%d_%H:%M:%S}
 
         {utcnow}
 
-            The current UTC date and time.
+            The current UTC date and time, by default in ISO-8601 format.
+            You can also supply your own `format string <https://docs.python.org/3.4/library/datetime.html#strftime-and-strptime-behavior>`_, e.g. {utcnow:%Y-%m-%d_%H:%M:%S}
 
         {user}
 
diff --git a/src/borg/helpers.py b/src/borg/helpers.py
--- a/src/borg/helpers.py
+++ b/src/borg/helpers.py
@@ -622,6 +622,16 @@ def partial_format(format, mapping):
     return format
 
 
+class DatetimeWrapper:
+    def __init__(self, dt):
+        self.dt = dt
+
+    def __format__(self, format_spec):
+        if format_spec == '':
+            format_spec = '%Y-%m-%dT%H:%M:%S'
+        return self.dt.__format__(format_spec)
+
+
 def format_line(format, data):
     try:
         return format.format(**data)
@@ -636,8 +646,8 @@ def replace_placeholders(text):
         'pid': os.getpid(),
         'fqdn': socket.getfqdn(),
         'hostname': socket.gethostname(),
-        'now': current_time.now(),
-        'utcnow': current_time.utcnow(),
+        'now': DatetimeWrapper(current_time.now()),
+        'utcnow': DatetimeWrapper(current_time.utcnow()),
         'user': uid2user(os.getuid(), os.getuid()),
         'uuid4': str(uuid.uuid4()),
         'borgversion': borg_version,
diff --git a/src/borg/testsuite/helpers.py b/src/borg/testsuite/helpers.py
--- a/src/borg/testsuite/helpers.py
+++ b/src/borg/testsuite/helpers.py
@@ -11,7 +11,7 @@
 
 from ..helpers import Location
 from ..helpers import Buffer
-from ..helpers import partial_format, format_file_size, parse_file_size, format_timedelta, format_line, PlaceholderError
+from ..helpers import partial_format, format_file_size, parse_file_size, format_timedelta, format_line, PlaceholderError, replace_placeholders
 from ..helpers import make_path_safe, clean_lines
 from ..helpers import prune_within, prune_split
 from ..helpers import get_cache_dir, get_keys_dir, get_nonces_dir
@@ -1035,3 +1035,9 @@ def test_format_line_erroneous():
         assert format_line('{invalid}', data)
     with pytest.raises(PlaceholderError):
         assert format_line('{}', data)
+
+
+def test_replace_placeholders():
+    now = datetime.now()
+    assert " " not in replace_placeholders('{now}')
+    assert int(replace_placeholders('{now:%Y}')) == now.year


Test patch: