2
# (C) Copyright 2003, 2004 Hewlett-Packard Development Company, L.P.
3
# (C) Copyright 2006, 2007 Novell, Inc.
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU Lesser General Public License as
7
# published by the Free Software Foundation; either version 2 of the
10
# This program is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
# Lesser General Public License for more details.
15
# You should have received a copy of the GNU Lesser General Public
16
# License along with this program; if not, write to the Free Software
17
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
# Author: Tim Potter <tpot@hp.com>
21
# Author: Bart Whiteley <bwhiteley@suse.de>
24
Subclasses of builtin Python types to remember CIM types. This is
25
necessary as we need to remember whether an integer property is a
26
uint8, uint16, uint32 etc, while still being able to treat it as a
30
from datetime import tzinfo, datetime, timedelta
33
class MinutesFromUTC(tzinfo):
34
"""Fixed offset in minutes from UTC."""
35
def __init__(self, offset):
36
self.__offset = timedelta(minutes = offset)
37
def utcoffset(self, dt):
42
class CIMType(object):
43
"""Base type for all CIM types."""
45
class CIMDateTime(CIMType) :
48
def __init__(self, dtarg):
49
"""Construct a new CIMDateTime
52
dtarg -- Can be a string in CIM datetime format, a datetime.datetime,
53
or a datetime.timedelta.
57
self.cimtype = 'datetime'
58
self.__timedelta = None
59
self.__datetime = None
60
if isinstance(dtarg, basestring):
61
date_pattern = re.compile(r'^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.(\d{6})([+|-])(\d{3})')
62
s = date_pattern.search(dtarg)
68
self.__datetime = datetime(int(g[0]), int(g[1]),
71
int(g[6]), MinutesFromUTC(offset))
73
tv_pattern = re.compile(r'^(\d{8})(\d{2})(\d{2})(\d{2})\.(\d{6})(:)(000)')
74
s = tv_pattern.search(dtarg)
76
raise ValueError('Invalid Datetime format "%s"' % dtarg)
79
self.__timedelta = timedelta(days=int(g[0]),
83
microseconds=int(g[4]))
84
elif isinstance(dtarg, datetime):
85
self.__datetime = dtarg;
86
elif isinstance(dtarg, timedelta):
87
self.__timedelta = dtarg
88
elif isinstance(dtarg, CIMDateTime):
89
self.__datetime = dtarg.__datetime
90
self.__timedelta = dtarg.__timedelta
92
raise ValueError('Expected datetime, timedelta, or string')
95
def minutes_from_utc(self):
96
"""Return the timezone as +/- minutes from UTC"""
98
if self.__datetime is not None and \
99
self.__datetime.utcoffset() is not None:
100
offset = self.__datetime.utcoffset().seconds / 60
101
if self.__datetime.utcoffset().days == -1:
102
offset = -(60*24 - offset)
107
return self.__datetime
111
return self.__timedelta
114
def is_interval(self):
115
return self.__timedelta is not None
118
def get_local_utcoffset():
119
"""Return minutes +/- UTC for the local timezone"""
120
utc = datetime.utcnow()
121
local = datetime.now()
123
return - int(float((utc - local).seconds) / 60 + .5)
125
return int(float((local - utc).seconds) / 60 + .5)
128
def now(cls, tzi=None):
130
tzi = MinutesFromUTC(cls.get_local_utcoffset())
131
return cls(datetime.now(tzi))
134
def fromtimestamp(cls, ts, tzi=None):
136
tzi = MinutesFromUTC(cls.get_local_utcoffset())
137
return cls(datetime.fromtimestamp(ts, tzi))
141
hour = self.__timedelta.seconds / 3600
142
minute = (self.__timedelta.seconds - hour * 3600) / 60
143
second = self.__timedelta.seconds - hour * 3600 - minute * 60
144
return '%08d%02d%02d%02d.%06d:000' % \
145
(self.__timedelta.days, hour, minute, second,
146
self.__timedelta.microseconds)
148
offset = self.minutes_from_utc
153
return '%d%02d%02d%02d%02d%02d.%06d%s%03d' % \
154
(self.__datetime.year, self.__datetime.month,
155
self.__datetime.day, self.__datetime.hour,
156
self.__datetime.minute, self.__datetime.second,
157
self.__datetime.microsecond, sign, offset)
160
return '%s(%s)'%(self.__class__.__name__, `str(self)`)
162
def __getstate__(self):
165
def __setstate__(self, arg):
168
def __cmp__(self, other):
171
elif not isinstance(other, CIMDateTime):
173
return (cmp(self.__datetime, other.__datetime) or
174
cmp(self.__timedelta, other.__timedelta))
179
class CIMInt(CIMType, long):
188
class Uint16(CIMInt):
191
class Sint16(CIMInt):
194
class Uint32(CIMInt):
197
class Sint32(CIMInt):
200
class Uint64(CIMInt):
203
class Sint64(CIMInt):
208
class CIMFloat(CIMType, float):
211
class Real32(CIMFloat):
214
class Real64(CIMFloat):
218
"""Return the CIM type name of an object as a string. For a list, the
219
type is the type of the first element as CIM arrays must be
222
if isinstance(obj, CIMType):
225
if isinstance(obj, bool):
228
if isinstance(obj, (str, unicode)):
231
if isinstance(obj, list):
232
return cimtype(obj[0])
234
if isinstance(obj, (datetime, timedelta)):
237
raise TypeError("Invalid CIM type for %s" % str(obj))
241
def atomic_to_cim_xml(obj):
242
"""Convert an atomic type to CIM external form"""
243
if isinstance(obj, bool):
249
elif isinstance(obj, CIMDateTime):
252
elif isinstance(obj, datetime):
253
return unicode(CIMDateTime(obj))
257
elif cimtype(obj) == 'real32':
259
elif cimtype(obj) == 'real64':
260
return u'%.16E' % obj