Date/time utils

A service’s self.time accesses convenience wrappers around Python’s datetime and Arrow’s objects.

UTC now

Call self.time.utcnow() to obtain current time in UTC. Default format is YYYY-MM-DD HH:mm:ss. Returns string unless told not to serialize the result.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from zato.server.service import Service

class MyService(Service):

    def handle(self):

        # Default
        now = self.time.utcnow()
        self.logger.info('Now (1) is %s', now)

        # Custom output format, still in UTC
        now = self.time.utcnow('DD-MM-YY HH:mm')
        self.logger.info('Now (2) is %s', now)

        # Don't serialize to string
        now = self.time.utcnow(needs_format=False)
        self.logger.info('Now (3) is %r', now)

Output in server logs:

INFO - Now (1) is 2015-01-26 13:34:24
INFO - Now (2) is 26-01-15 13:34
INFO - Now (3) is <Arrow [2015-01-26T13:34:24.738026+00:00]>

Today

Returns current date. Default format is YYYY-MM-DD in UTC - both can be overridden. Converts output to string unless overridden.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from zato.server.service import Service

class MyService(Service):

    def handle(self):

        # Default
        today = self.time.today()
        self.logger.info('Today in UTC (1) is %s', today)

        # UTC, custom format
        today = self.time.today('DDMMYY')
        self.logger.info('Today in UTC (2) is %s', today)

        # Don't serialize to string
        today = self.time.today(needs_format=False)
        self.logger.info('Today in UTC (3) is %r', today)

        # A user-provided timezone
        today = self.time.today(tz='Pacific/Fiji')
        self.logger.info('Today in Suva is %s', today)

Output in logs:

INFO - Today in UTC (1) is 2015-01-26
INFO - Today in UTC (2) is 260115
INFO - Today in UTC (3) is <Arrow [2015-01-26T00:00:00+00:00]>
INFO - Today in Suva is 2015-01-27

Reformatting

Dates and time can be converted between formats using self.time.reformat - the method accepts a value, its format and a format it needs to be changed to. The value can be a string, datetime or an Arrow object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from zato.server.service import Service

class MyService(Service):

    def handle(self):

        # Convert from DD-MM-YYYY to YY.MM.DD

        value = '15-11-2019'
        self.logger.info('Was: %s', value)

        value = self.time.reformat(value, 'DD-MM-YYYY', 'YY.MM.DD')
        self.logger.info('Now: %s', value)
INFO - Was: 15-11-2019
INFO - Now: 19.11.15

Anticipating the need to change source or target formats it's possible to store either or both in Redis so they are read in run-time without hardcoding anything in code.

Now instead of exact formats their names prefixed with 'kvdb:' are used. The prefix is stripped away and the names point to Redis keys that will contain the exact formats.

The pattern to use in Redis is kvdb:date-format:$name where $name is the name provided on input to self.time.reformat. For instance, a 'crm' format name should be stored in Redis under kvdb:date-format:crm key.

Supposing there are Redis keys as follows:

127.0.0.1:6379> SET kvdb:date-format:crm "YY-MM-DD HH:mm"
OK
127.0.0.1:6379> SET kvdb:date-format:erp MM-DD-YY
OK

The following code will look up formats in Redis in order to reformat date from CRM to the format ERP expects. Should formats change, no updates to the code of the service will be needed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from zato.server.service import Service

class MyService(Service):

    def handle(self):

        # Convert from DD-MM-YYYY to YY.MM.DD

        value = '15-11-2019 13:17'
        self.logger.info('Was: %s', value)

        value = self.time.reformat(value, 'kvdb:crm', 'kvdb:erp')
INFO - Was: 15-11-2019 13:17
INFO - Now: 11-20-15