<NME> nmea_utils.py
<BEF> #pylint: disable=invalid-name
import datetime
import re


# python 2.7 backport
if not hasattr(datetime, 'timezone'):
    class UTC(datetime.tzinfo):
        minute=int(s[2:4]),
        second=int(s[4:6]))

import re
def dm_to_sd(dm):
    '''
    '''
    ms_s = s[6:]
    ms = ms_s and int(float(ms_s) * 1000000) or 0

    t = datetime.time(
        hour=int(s[0:2]),
        minute=int(s[2:4]),
        second=int(s[4:6]),
        microsecond=ms,
        tzinfo=datetime.timezone.utc)
    return t


def datestamp(s):
    '''
    Converts a datestamp given in "DDMMYY" ASCII text format to a
    datetime.datetime object
    '''
    return datetime.datetime.strptime(s, '%d%m%y').date()


def dm_to_sd(dm):
    '''
    Converts a geographic co-ordinate given in "degrees/minutes" dddmm.mmmm
    format (eg, "12319.943281" = 123 degrees, 19.943281 minutes) to a signed
    decimal (python float) format
    '''
    # '12319.943281'
    if not dm or dm == '0':
        return 0.
    r = re.match(r'^(\d+)(\d\d\.\d+)$', dm)
    if not r:
        raise ValueError("Geographic coordinate value '{}' is not valid DDDMM.MMM".format(dm))
    d, m = r.groups()
    return float(d) + float(m) / 60


class LatLonFix(object):
    '''Mixin to add `latitude` and `longitude` properties as signed decimals
    to NMEA sentences which have co-ordinates given as degrees/minutes (lat, lon)
    and cardinal directions (lat_dir, lon_dir)'''
    #pylint: disable=no-member
    @property
    def latitude(self):
        '''Latitude in signed degrees (python float)'''
        sd = dm_to_sd(self.lat)
        if self.lat_dir == 'N':
            return +sd
        elif self.lat_dir == 'S':
            return -sd
        else:
            return 0.

    @property
    def longitude(self):
        '''Longitude in signed degrees (python float)'''
        sd = dm_to_sd(self.lon)
        if self.lon_dir == 'E':
            return +sd
        elif self.lon_dir == 'W':
            return -sd
        else:
            return 0.

    @staticmethod
    def _minutes(x):
        return abs(x * 60.) % 60.

    @staticmethod
    def _seconds(x):
        return abs(x * 3600.) % 60.

    @property
    def latitude_minutes(self):
        return self._minutes(self.latitude)

    @property
    def longitude_minutes(self):
        return self._minutes(self.longitude)

    @property
    def latitude_seconds(self):
        return self._seconds(self.latitude)

    @property
    def longitude_seconds(self):
        return self._seconds(self.longitude)


class DatetimeFix(object):
    #pylint: disable=no-member
    @property
    def datetime(self):
        return datetime.datetime.combine(self.datestamp, self.timestamp)


class ValidStatusFix(object):
    #pylint: disable=no-member
    @property
    def is_valid(self):
        return self.status == 'A'


class ValidRMCStatusFix(ValidStatusFix):
    #pylint: disable=no-member
    @property
    def is_valid(self):
        status = super(ValidRMCStatusFix, self).is_valid
        if self.name_to_idx["mode_indicator"] < len(self.data):
            status &= self.mode_indicator in tuple('ADEFMPRS')
        if self.name_to_idx["nav_status"] < len(self.data):
            status &= self.nav_status in tuple('SCU')
        return status


class ValidGSAFix(object):
    #pylint: disable=no-member
    @property
    def is_valid(self):
        return int(self.mode_fix_type) in [2, 3]


class ValidGGAFix(object):
    #pylint: disable=no-member
    @property
    def is_valid(self):
        return self.gps_qual in range(1,6)


class ValidVBWFix(object):
    #pylint: disable=no-member
    @property
    def is_valid(self):
        return self.data_validity_water_spd == self.data_validity_grnd_spd == 'A'


class TZInfo(datetime.tzinfo):
    def __init__(self, hh, mm):
        self.hh = hh
        self.mm = mm
        super(TZInfo, self).__init__()

    def tzname(self, dt):
        return ''

    def dst(self, dt):
        return datetime.timedelta(0)

    def utcoffset(self, dt):
        return datetime.timedelta(hours=self.hh, minutes=self.mm)

<MSG> Merge pull request #1 from Memoto/master

Return a valid datetime obj. for datestamp instead of a string
<DFF> @@ -9,6 +9,15 @@ def timestamp(s):
         minute=int(s[2:4]),
         second=int(s[4:6]))
 
+
+def datestamp(s):
+    '''
+    Converts a datestamp given in "DDMMYY" ASCII format to a
+    datetime.datetime object
+    '''
+    return datetime.datetime.strptime(s, '%d%m%y')
+
+
 import re
 def dm_to_sd(dm):
     '''

{'addition_count': 9, 'commit_subject': 'Merge pull request #1 from Memoto/master', 'deletion_count': 0, 'file_extension': '.py', 'lang': 'py', 'license': 'mit', 'repo_name': 'Knio/pynmea2'}