<commit_before># -*- test-case-name: vumi.tests.test_message -*-

import json
from uuid import uuid4
from datetime import datetime

from errors import MissingMessageField, InvalidMessageField

from vumi.utils import to_kwargs


# This is the date format we work with internally
VUMI_DATE_FORMAT = "%Y-%m-%d %H:%M:%S.%f"


def format_vumi_date(timestamp):
    """Format a datetime object using the Vumi date format.

    :param datetime timestamp:
        The datetime object to format.
    :return str:
        The timestamp formatted as a string.
    """
    return timestamp.strftime(VUMI_DATE_FORMAT)


def parse_vumi_date(value):
    """Parse a timestamp string in using the Vumi date format.

    :param str value:
        The string to parse.
    :return datetime:
        A datetime object representing the timestamp.
    """
    return datetime.strptime(value, VUMI_DATE_FORMAT)


def date_time_decoder(json_object):
    for key, value in json_object.items():
        try:
            json_object[key] = parse_vumi_date(value)
        except ValueError:
            continue
        except TypeError:
            continue
    return json_object


class JSONMessageEncoder(json.JSONEncoder):
    """A JSON encoder that is able to serialize datetime"""
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.strftime(VUMI_DATE_FORMAT)
        return super(JSONMessageEncoder, self).default(obj)


def from_json(json_string):
    return json.loads(json_string, object_hook=date_time_decoder)


def to_json(obj):
    return json.dumps(obj, cls=JSONMessageEncoder)


class Message(object):
    """
    A unified message object used by Vumi when transmitting messages over AMQP
    and occassionally as a standardised JSON format for use in external APIs.

    The special ``.cache`` property stores a dictionary of data that is not
    stored by the :class:`vumi.fields.VumiMessage` field and hence not stored
    by Vumi's message store.<commit_msg>Correct docstring and use format_vumi_date in to_json.<commit_after># -*- test-case-name: vumi.tests.test_message -*-

import json
from uuid import uuid4
from datetime import datetime

from errors import MissingMessageField, InvalidMessageField

from vumi.utils import to_kwargs


# This is the date format we work with internally
VUMI_DATE_FORMAT = "%Y-%m-%d %H:%M:%S.%f"


def format_vumi_date(timestamp):
    """Format a datetime object using the Vumi date format.

    :param datetime timestamp:
        The datetime object to format.
    :return str:
        The timestamp formatted as a string.
    """
    return timestamp.strftime(VUMI_DATE_FORMAT)


def parse_vumi_date(value):
    """Parse a timestamp string using the Vumi date format.

    :param str value:
        The string to parse.
    :return datetime:
        A datetime object representing the timestamp.
    """
    return datetime.strptime(value, VUMI_DATE_FORMAT)


def date_time_decoder(json_object):
    for key, value in json_object.items():
        try:
            json_object[key] = parse_vumi_date(value)
        except ValueError:
            continue
        except TypeError:
            continue
    return json_object


class JSONMessageEncoder(json.JSONEncoder):
    """A JSON encoder that is able to serialize datetime"""
    def default(self, obj):
        if isinstance(obj, datetime):
            return format_vumi_date(obj)
        return super(JSONMessageEncoder, self).default(obj)


def from_json(json_string):
    return json.loads(json_string, object_hook=date_time_decoder)


def to_json(obj):
    return json.dumps(obj, cls=JSONMessageEncoder)


class Message(object):
    """
    A unified message object used by Vumi when transmitting messages over AMQP
    and occassionally as a standardised JSON format for use in external APIs.

    The special ``.cache`` property stores a dictionary of data that is not
    stored by the :class:`vumi.fields.VumiMessage` field and hence not stored
    by Vumi's message store.
{'fraction_non_alphanumeric': 0.0754434174369223, 'fraction_numerical': 0.0004996252810392206, 'mean_word_length': 3.3053763440860213, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2682173', 'n_tokens_mistral': 1155, 'n_tokens_neox': 1116, 'n_words': 392}