VirtualBox

Changeset 83357 in vbox for trunk


Ignore:
Timestamp:
Mar 21, 2020 1:01:30 PM (5 years ago)
Author:
vboxsync
Message:

common/utils.py: Added a few functions of parsing and managing iso timestamps.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/common/utils.py

    r82968 r83357  
    14481448    return (sTsPrf, sTsIso);
    14491449
     1450class UtcTzInfo(datetime.tzinfo):
     1451    """UTC TZ Info Class"""
     1452    def utcoffset(self, _):
     1453        return datetime.timedelta(0);
     1454    def tzname(self, _):
     1455        return "UTC";
     1456    def dst(self, _):
     1457        return datetime.timedelta(0);
     1458
     1459class GenTzInfo(datetime.tzinfo):
     1460    """Generic TZ Info Class"""
     1461    def __init__(self, offInMin):
     1462        datetime.tzinfo.__init__(self);
     1463        self.offInMin = offInMin;
     1464    def utcoffset(self, _):
     1465        return datetime.timedelta(minutes = self.offInMin);
     1466    def tzname(self, _):
     1467        if self.offInMin >= 0:
     1468            return "+%02d%02d" % (self.offInMin // 60, self.offInMin % 60);
     1469        return "-%02d%02d" % (-self.offInMin // 60, -self.offInMin % 60);
     1470    def dst(self, _):
     1471        return datetime.timedelta(0);
     1472
    14501473def formatIsoTimestamp(oNow):
    14511474    """Formats the datetime object as an ISO timestamp."""
    1452     assert oNow.tzinfo is None;
     1475    assert oNow.tzinfo is None or isinstance(oNow.tzinfo, UtcTzInfo);
    14531476    sTs = '%s.%09uZ' % (oNow.strftime('%Y-%m-%dT%H:%M:%S'), oNow.microsecond * 1000);
    14541477    return sTs;
     
    14581481    return formatIsoTimestamp(datetime.datetime.utcnow());
    14591482
     1483def convertDateTimeToZulu(oDateTime):
     1484    """ Converts oDateTime to zulu time if it has timezone info. """
     1485    if oDateTime.tzinfo is not None:
     1486        oDateTime = oDateTime.astimezone(UtcTzInfo());
     1487    else:
     1488        oDateTime = oDateTime.replace(tzinfo = UtcTzInfo());
     1489    return oDateTime;
     1490
     1491def parseIsoTimestamp(sTs):
     1492    """
     1493    Parses a typical ISO timestamp, returing a datetime object, reasonably
     1494    forgiving, but will throw weird indexing/conversion errors if the input
     1495    is malformed.
     1496    """
     1497    # YYYY-MM-DD
     1498    iYear  = int(sTs[0:4]);
     1499    assert(sTs[4] == '-');
     1500    iMonth = int(sTs[5:7]);
     1501    assert(sTs[7] == '-');
     1502    iDay   = int(sTs[8:10]);
     1503
     1504    # Skip separator
     1505    sTime = sTs[10:];
     1506    while sTime[0] in 'Tt \t\n\r':
     1507        sTime = sTime[1:];
     1508
     1509    # HH:MM:SS
     1510    iHour = int(sTime[0:2]);
     1511    assert(sTime[2] == ':');
     1512    iMin  = int(sTime[3:5]);
     1513    assert(sTime[5] == ':');
     1514    iSec  = int(sTime[6:8]);
     1515
     1516    # Fraction?
     1517    offTime = 8;
     1518    iMicroseconds = 0;
     1519    if offTime < len(sTime) and sTime[offTime] in '.,':
     1520        offTime += 1;
     1521        cchFraction = 0;
     1522        while offTime + cchFraction < len(sTime) and sTime[offTime + cchFraction] in '0123456789':
     1523            cchFraction += 1;
     1524        if cchFraction > 0:
     1525            iMicroseconds = int(sTime[offTime : (offTime + cchFraction)]);
     1526            offTime += cchFraction;
     1527            while cchFraction < 6:
     1528                iMicroseconds *= 10;
     1529                cchFraction += 1;
     1530            while cchFraction > 6:
     1531                iMicroseconds = iMicroseconds // 10;
     1532                cchFraction -= 1;
     1533
     1534    # Naive?
     1535    if offTime >= len(sTime):
     1536        return datetime.datetime(iYear, iMonth, iDay, iHour, iMin, iSec, iMicroseconds);
     1537
     1538    # Zulu?
     1539    if offTime >= len(sTime) or sTime[offTime] in 'Zz':
     1540        return datetime.datetime(iYear, iMonth, iDay, iHour, iMin, iSec, iMicroseconds, tzinfo = UtcTzInfo());
     1541
     1542    # Some kind of offset afterwards, and strptime is useless. sigh.
     1543    if sTime[offTime] in '+-':
     1544        chSign = sTime[offTime];
     1545        offTime += 1;
     1546        cMinTz = int(sTime[offTime : (offTime + 2)]) * 60;
     1547        offTime += 2;
     1548        if offTime  < len(sTime) and sTime[offTime] in ':':
     1549            offTime += 1;
     1550        if offTime + 2 <= len(sTime):
     1551            cMinTz += int(sTime[offTime : (offTime + 2)]);
     1552            offTime += 2;
     1553        assert offTime == len(sTime);
     1554        if chSign == '-':
     1555            cMinTz = -cMinTz;
     1556        return datetime.datetime(iYear, iMonth, iDay, iHour, iMin, iSec, iMicroseconds, tzinfo = GenTzInfo(cMinTz));
     1557    assert False, sTs;
     1558    return datetime.datetime(iYear, iMonth, iDay, iHour, iMin, iSec, iMicroseconds);
     1559
     1560def normalizeIsoTimestampToZulu(sTs):
     1561    """
     1562    Takes a iso timestamp string and normalizes it (basically parseIsoTimestamp
     1563    + convertDateTimeToZulu + formatIsoTimestamp).
     1564    Returns ISO tiemstamp string.
     1565    """
     1566    return formatIsoTimestamp(convertDateTimeToZulu(parseIsoTimestamp(sTs)));
    14601567
    14611568def getLocalHourOfWeek():
     
    22322339        self.assertEqual(parseIntervalSeconds('1 hour,2m ; 5second'), (3725, None));
    22332340
     2341    def testZuluNormalization(self):
     2342        self.assertEqual(normalizeIsoTimestampToZulu('2011-01-02T03:34:25.000000000Z'), '2011-01-02T03:34:25.000000000Z');
     2343        self.assertEqual(normalizeIsoTimestampToZulu('2011-01-02T03:04:25-0030'), '2011-01-02T03:34:25.000000000Z');
     2344        self.assertEqual(normalizeIsoTimestampToZulu('2011-01-02T03:04:25+0030'), '2011-01-02T02:34:25.000000000Z');
     2345        self.assertEqual(normalizeIsoTimestampToZulu('2020-03-20T20:47:39,832312863+01:00'), '2020-03-20T19:47:39.832312000Z');
     2346        self.assertEqual(normalizeIsoTimestampToZulu('2020-03-20T20:47:39,832312863-02:00'), '2020-03-20T22:47:39.832312000Z');
     2347
    22342348    def testHasNonAsciiChars(self):
    22352349        self.assertEqual(hasNonAsciiCharacters(''), False);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette