diff --git a/fmt/fmt.py b/fmt/fmt.py
index 019eab3..8344646 100644
--- a/fmt/fmt.py
+++ b/fmt/fmt.py
@@ -104,7 +104,7 @@ class Expression(Node):
     def __init__(self, expr, fmt, name='name'):
         self._expr = expr
         self._name = name
-        self._fmt = fmt.replace(expr, name).replace(' ', '')
+        self._fmt = name.join(s.strip() for s in fmt.split(expr))
 
     def generate(self, namespace):
         ns = {}
@@ -314,15 +314,37 @@ class Parser(object):
         #   <optional : format specifier>
         # } <text> ...'''
         expr = None
-        splitd = node_str.rsplit(':', 1)
-        if len(splitd) > 1:
-            left, fmt_spec = splitd
-            if not fmt_spec:
+        if ':' in node_str:
+            if node_str.startswith('('):
+                brackets = 1
+                for i, c in enumerate(node_str[1:]):
+                    if c == '(':
+                        brackets += 1
+                    elif c == ')':
+                        brackets -= 1
+                        if brackets == 0:
+                            break
+                i += 1
+                if brackets != 0:
+                    raise SyntaxError('unexpected EOF at {}'.format(
+                        node_str[i]))
+                i += 1
+                if len(node_str) > i+2 and node_str[i] == '(':
+                    i += 2
+                    if node_str[i] != ':':
+                        raise SyntaxError('unexpected EOF at {}'.format(
+                            node_str[i]))
+                    left, fmt_spec = node_str[:i], node_str[i+1:]
+                else:
+                    left, fmt_spec = node_str, None
+            else:
+                left, fmt_spec = node_str.split(':', 1)
+                if 'lambda' in left:
+                    left = node_str
+            if fmt_spec is not None and not fmt_spec:
                 raise SyntaxError('need format specifier after ":"')
-            elif 'lambda' in left:
-                left = node_str
         else:
-            left = splitd[0]
+            left = node_str
 
         splitd = left.rsplit('!', 1)
         if len(splitd) > 1:

datetime format
- `f('{datetime(1994, 11, 6, 0, 0, 0):%Y-%m-%d %H:%M:%S}')`

- `f('{(lambda: datetime(1994, 11, 6, 0, 0, 0))():%Y-%m-%d %H:%M:%S}')`
diff --git a/tests/test_fmt.py b/tests/test_fmt.py
index 19033b8..36b3765 100644
--- a/tests/test_fmt.py
+++ b/tests/test_fmt.py
@@ -133,6 +133,10 @@ def test_fmt():
             f('int:{23:d}, hex:{23:x}, oct:{23:#o}, bin:{23:#b}'))
     assert '1,234,567,890' == f('{1234567890:,}')
     assert '1994-11-06' == f('{datetime(1994, 11, 6):%Y-%m-%d}')
+    assert '1994-11-06 00:00:00' == f('{datetime(1994, 11, 6, 0, 0, 0):%Y-%m-%d %H:%M:%S}')
+    assert 'None' == f('{(lambda: None)()}')
+    assert '1994:11:06' == f('{(lambda: datetime(1994, 11, 6))():%Y:%m:%d}')
+    assert '1994-11-06 00:00:00' == f('{(lambda: datetime(1994, 11, 6, 0, 0, 0))():%Y-%m-%d %H:%M:%S}')
 
     assert g_foo not in f._g_ns
     assert g_bar not in f._g_ns

pip install -e .
parse_log_pytest
pytest
pytest flake8 pylint
apt-get update apt-get install -y gcc
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
astroid==3.3.9
dill==0.3.9
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
flake8==7.2.0
-e git+https://github.com/damnever/fmt.git@12cc50185a8ff90db1ac17f862568a4780fee774#egg=fmt
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
isort==6.0.1
mccabe==0.7.0
packaging @ file:///croot/packaging_1734472117206/work
platformdirs==4.3.7
pluggy @ file:///croot/pluggy_1733169602837/work
pycodestyle==2.13.0
pyflakes==3.3.2
pylint==3.3.6
pytest @ file:///croot/pytest_1738938843180/work
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
tomlkit==0.13.2
typing_extensions==4.13.0

name: fmt
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - astroid==3.3.9
      - dill==0.3.9
      - flake8==7.2.0
      - isort==6.0.1
      - mccabe==0.7.0
      - platformdirs==4.3.7
      - pycodestyle==2.13.0
      - pyflakes==3.3.2
      - pylint==3.3.6
      - tomlkit==0.13.2
      - typing-extensions==4.13.0
prefix: /opt/conda/envs/fmt

tests/test_fmt.py::test_fmt
tests/test_fmt.py::test_parsed_nodes_been_cached tests/test_fmt.py::test_namespace tests/test_fmt.py::test_closure_namespace
fmt/fmt.py
fmt/fmt.py