Customize timestamps in Python logging

Set logging datefmt, include milliseconds, choose local time or UTC, and supply formatter settings through dictConfig.

Best practices
Customize timestamps in Python logging illustration

Include %(asctime)s in a logging formatter and set datefmt to choose the timestamp layout. The formatter uses strftime directives for this date format.

Configure a timestamped handler

import logging

handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(
    fmt='%(asctime)s [%(levelname)s] %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S',
))
logger = logging.getLogger('example')
logger.setLevel(logging.INFO)
logger.propagate = False
logger.addHandler(handler)
logger.info('Application started')

Set this up once during startup. The logger’s INFO threshold matters: changing a formatter alone does not make an INFO record pass the default WARNING threshold.

Include milliseconds and a timezone

The default asctime format includes comma-separated milliseconds. Supplying datefmt replaces that default layout; to add milliseconds explicitly:

formatter = logging.Formatter(
    '%(asctime)s.%(msecs)03d %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S',
)

For a timestamp with an offset, use datefmt='%Y-%m-%dT%H:%M:%S%z'. For an ISO 8601 timestamp including both milliseconds and a colon-separated offset, override formatTime:

from datetime import datetime, timezone

class ISOFormatter(logging.Formatter):
    def formatTime(self, record, datefmt=None):
        return datetime.fromtimestamp(
            record.created, timezone.utc
        ).isoformat(timespec='milliseconds')

handler.setFormatter(ISOFormatter('%(asctime)s %(message)s'))

This override intentionally emits UTC regardless of datefmt. Do not assume %f works with the default formatter: its time formatting uses time.strftime, not datetime.strftime.

Common date directives

Directive Meaning
%Y Four-digit year
%m, %d Month and day
%H, %M, %S 24-hour time: hours, minutes, seconds
%z Numeric timezone offset

FAQ

Are timestamps local or UTC by default?

Local time. For a standard formatter, set formatter.converter = time.gmtime after importing time to use UTC. Assigning logging.Formatter.converter = time.gmtime changes the class-wide default, so use the instance setting when only one formatter should change.

How do I set the format through dictConfig?

In the relevant entry under formatters, include 'format': '%(asctime)s %(message)s' and 'datefmt': '%Y-%m-%d %H:%M:%S'. The handler must reference that formatter, and logger/handler levels still determine which records appear.

See Python logging reference.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting