Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
blpapi / datetime.py
Size: Mime:
# datetime.py

"""Utilities that deal with blpapi.Datetime data type"""

from __future__ import absolute_import
from __future__ import division

import datetime as _dt

from . import internals
from . import utils
from .compat import with_metaclass


# pylint: disable=no-member,useless-object-inheritance

@with_metaclass(utils.MetaClassForClassesWithEnums)
class FixedOffset(_dt.tzinfo):
    """Time zone information.

    Represents time zone information to be used with Python standard library
    datetime classes.

    This class is intended to be used as ``tzinfo`` for Python standard library
    :class:`datetime.datetime` and :class:`datetime.time` classes. These
    classes are accepted by the blpapi package to set :attr:`~DataType.DATE`,
    :attr:`~DataType.TIME` or :attr:`~DataType.DATETIME` elements. For example,
    the :attr:`~DataType.DATETIME` element of a request could be set as::

        value = datetime.datetime(1941, 6, 22, 4, 0, tzinfo=FixedOffset(4*60))
        request.getElement("last_trade").setValue(value)

    The :attr:`~DataType.TIME` element could be set in a similar way::

        value = datetime.time(9, 0, 1, tzinfo=FixedOffset(-5*60))
        request.getElement("session_open").setValue(value)

    Note that you could use any other implementations of
    :class:`datetime.tzinfo` with BLPAPI-Py, for example the widely used
    ``pytz`` package (https://pypi.python.org/pypi/pytz/).

    For more details see datetime module documentation at
    https://docs.python.org/library/datetime.html
    """

    def __init__(self, offsetInMinutes=0):
        """
        Args:
            offsetInMinutes (int): Offset from UTC in minutes

        Creates an object that implements :class:`datetime.tzinfo` interface
        and represents a timezone with the specified ``offsetInMinutes`` from
        UTC.
        """
        self.__offset = _dt.timedelta(minutes=offsetInMinutes)

    def utcoffset(self, dt):
        del dt
        return self.__offset

    def dst(self, dt): # pylint: disable=no-self-use
        del dt
        return _dt.timedelta(0)

    def tzname(self, dt):
        del dt
        return self.__offset

    def getOffsetInMinutes(self):
        """
        Returns:
            int: Offset from UTC in minutes
        """
        return self.__offset.days * 24 * 60 + self.__offset.seconds // 60

    def __hash__(self):
        """x.__hash__() <==> hash(x)"""
        return self.getOffsetInMinutes()

    def __cmp__(self, other):
        """Let the comparison operations work based on the time delta.
        NOTE: (compatibility) this method have no special meaning in python3,
        we should use __eq__, __lt__ and __le__ instead. Built-in cmp function
        is also gone. This method can be called only from python2."""
        return cmp(self.getOffsetInMinutes(), other.getOffsetInMinutes()) # pylint: disable=undefined-variable

    def __eq__(self, other):
        """Let the equality operator work based on the time delta."""
        return self.getOffsetInMinutes() == other.getOffsetInMinutes()

    def __lt__(self, other):
        """Let the comparison operator work based on the time delta."""
        return self.getOffsetInMinutes() < other.getOffsetInMinutes()

    def __le__(self, other):
        """Let the comparison operator work based on the time delta."""
        return self.getOffsetInMinutes() <= other.getOffsetInMinutes()


# UTC timezone
UTC = FixedOffset(0)


class _DatetimeUtil(object):
    """Utility methods that deal with BLPAPI dates and times."""
    @staticmethod
    def convertToNative(blpapiDatetimeObj):
        """Convert BLPAPI Datetime object to a suitable Python object."""

        isHighPrecision = isinstance(
            blpapiDatetimeObj,
            internals.blpapi_HighPrecisionDatetime_tag)

        if not isHighPrecision:
            raise ValueError(
                "Datetime object is not high precision",
                blpapiDatetimeObj)

        blpapiDatetime = blpapiDatetimeObj.datetime
        parts = blpapiDatetime.parts
        hasDate = parts & internals.DATETIME_DATE_PART == \
            internals.DATETIME_DATE_PART
        hasTime = parts & internals.DATETIME_TIMEFRACSECONDS_PART != 0
        microsecs = (blpapiDatetime.milliSeconds * 1000 +
                     blpapiDatetimeObj.picoseconds // 1000 // 1000) \
            if parts & internals.DATETIME_FRACSECONDS_PART else 0
        tzinfo = FixedOffset(blpapiDatetime.offset) if parts & \
            internals.DATETIME_OFFSET_PART else None
        if hasDate:
            if hasTime:
                return _dt.datetime(blpapiDatetime.year,
                                    blpapiDatetime.month,
                                    blpapiDatetime.day,
                                    blpapiDatetime.hours,
                                    blpapiDatetime.minutes,
                                    blpapiDatetime.seconds,
                                    microsecs,
                                    tzinfo)
            # Skip an offset, because it's not informative in case of
            # there is a date without the time
            return _dt.date(blpapiDatetime.year,
                            blpapiDatetime.month,
                            blpapiDatetime.day)

        if not hasTime:
            raise ValueError(
                "Datetime object misses both time and date parts",
                blpapiDatetime)
        return _dt.time(blpapiDatetime.hours,
                        blpapiDatetime.minutes,
                        blpapiDatetime.seconds,
                        microsecs,
                        tzinfo)
    @staticmethod
    def convertToNativeNotHighPrecision(blpapiDatetime):
        """Convert BLPAPI Datetime object to a suitable Python object.
        This version should only be used for logging callback which does not
        provide a high precision datetime alternative."""

        parts = blpapiDatetime.parts
        hasDate = parts & internals.DATETIME_DATE_PART == \
            internals.DATETIME_DATE_PART
        hasTime = parts & internals.DATETIME_TIME_PART == \
            internals.DATETIME_TIME_PART
        microsecs = blpapiDatetime.milliSeconds * 1000 if parts & \
            internals.DATETIME_MILLISECONDS_PART else 0
        tzinfo = FixedOffset(blpapiDatetime.offset) if parts & \
            internals.DATETIME_OFFSET_PART else None
        if hasDate:
            if hasTime:
                return _dt.datetime(blpapiDatetime.year,
                                    blpapiDatetime.month,
                                    blpapiDatetime.day,
                                    blpapiDatetime.hours,
                                    blpapiDatetime.minutes,
                                    blpapiDatetime.seconds,
                                    microsecs,
                                    tzinfo)
            # Skip an offset, because it's not informative in case of
            # there is a date without the time
            return _dt.date(blpapiDatetime.year,
                            blpapiDatetime.month,
                            blpapiDatetime.day)

        if not hasTime:
            raise ValueError(
                "Datetime object misses both time and date parts",
                blpapiDatetime)
        return _dt.time(blpapiDatetime.hours,
                        blpapiDatetime.minutes,
                        blpapiDatetime.seconds,
                        microsecs,
                        tzinfo)

    @staticmethod
    def isDatetime(dtime):
        """Return True if the parameter is one of Python date/time objects."""
        return isinstance(dtime, (_dt.datetime, _dt.date, _dt.time))

    @staticmethod
    def convertToBlpapi(dtime):
        "Convert a Python date/time object to a BLPAPI Datetime object."""
        highPrecDatetime = internals.blpapi_HighPrecisionDatetime_tag()
        res = highPrecDatetime.datetime
        offset = None
        if isinstance(dtime, _dt.datetime):
            offset = dtime.utcoffset()
            res.year = dtime.year
            res.month = dtime.month
            res.day = dtime.day
            res.hours = dtime.hour
            res.minutes = dtime.minute
            res.seconds = dtime.second
            (res.milliSeconds, highPrecDatetime.picoseconds) = \
                    divmod(dtime.microsecond, 1000)
            highPrecDatetime.picoseconds *= 1000 * 1000
            res.parts = internals.DATETIME_DATE_PART | \
                internals.DATETIME_TIMEFRACSECONDS_PART
        elif isinstance(dtime, _dt.date):
            res.year = dtime.year
            res.month = dtime.month
            res.day = dtime.day
            res.parts = internals.DATETIME_DATE_PART
        elif isinstance(dtime, _dt.time):
            offset = dtime.utcoffset()
            res.hours = dtime.hour
            res.minutes = dtime.minute
            res.seconds = dtime.second
            (res.milliSeconds, highPrecDatetime.picoseconds) = \
                    divmod(dtime.microsecond, 1000)
            highPrecDatetime.picoseconds *= 1000 * 1000
            res.parts = internals.DATETIME_TIMEFRACSECONDS_PART
        else:
            raise TypeError("Datetime could be created only from \
datetime.datetime, datetime.date or datetime.time")
        if offset is not None:
            res.offset = offset.seconds // 60
            res.parts |= internals.DATETIME_OFFSET_PART
        return highPrecDatetime

__copyright__ = """
Copyright 2012. Bloomberg Finance L.P.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:  The above
copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
"""