Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2from __future__ import unicode_literals 

3import datetime 

4import re 

5import math 

6 

7 

8DTM_TZ_RE = re.compile(r"(\d+(?:\.\d+)?)(?:([+-]\d{2})(\d{2}))?") 

9 

10 

11class _UTCOffset(datetime.tzinfo): 

12 """Fixed offset timezone from UTC.""" 

13 def __init__(self, minutes): 

14 """``minutes`` is a offset from UTC, negative for west of UTC""" 

15 self.minutes = minutes 

16 

17 def utcoffset(self, dt): 

18 return datetime.timedelta(minutes=self.minutes) 

19 

20 def tzname(self, dt): 

21 minutes = abs(self.minutes) 

22 return "{0}{1:02}{2:02}".format("-" if self.minutes < 0 else "+", minutes // 60, minutes % 60) 

23 

24 def dst(self, dt): 

25 return datetime.timedelta(0) 

26 

27 

28def parse_datetime(value): 

29 """Parse hl7 DTM string ``value`` :py:class:`datetime.datetime`. 

30 

31 ``value`` is of the format YYYY[MM[DD[HH[MM[SS[.S[S[S[S]]]]]]]]][+/-HHMM] 

32 or a ValueError will be raised. 

33 

34 :rtype: :py:;class:`datetime.datetime` 

35 """ 

36 if not value: 

37 return None 

38 

39 # Split off optional timezone 

40 dt_match = DTM_TZ_RE.match(value) 

41 if not dt_match: 

42 raise ValueError("Malformed HL7 datetime {0}".format(value)) 

43 dtm = dt_match.group(1) 

44 tzh = dt_match.group(2) 

45 tzm = dt_match.group(3) 

46 if tzh and tzm: 

47 minutes = int(tzh) * 60 

48 minutes += math.copysign(int(tzm), minutes) 

49 tzinfo = _UTCOffset(minutes) 

50 else: 

51 tzinfo = None 

52 

53 precision = len(dtm) 

54 

55 if precision >= 4: 

56 year = int(dtm[0:4]) 

57 else: 

58 raise ValueError("Malformed HL7 datetime {0}".format(value)) 

59 

60 if precision >= 6: 

61 month = int(dtm[4:6]) 

62 else: 

63 month = 1 

64 

65 if precision >= 8: 

66 day = int(dtm[6:8]) 

67 else: 

68 day = 1 

69 

70 if precision >= 10: 

71 hour = int(dtm[8:10]) 

72 else: 

73 hour = 0 

74 

75 if precision >= 12: 

76 minute = int(dtm[10:12]) 

77 else: 

78 minute = 0 

79 

80 if precision >= 14: 

81 delta = datetime.timedelta(seconds=float(dtm[12:])) 

82 second = delta.seconds 

83 microsecond = delta.microseconds 

84 else: 

85 second = 0 

86 microsecond = 0 

87 

88 return datetime.datetime(year, month, day, hour, minute, second, microsecond, tzinfo=tzinfo)