|
1 ############################################################################## |
|
2 # Copyright (c) 2002 Zope Foundation and Contributors. |
|
3 # All Rights Reserved. |
|
4 # |
|
5 # This software is subject to the provisions of the Zope Public License, |
|
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. |
|
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED |
|
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
|
10 # FOR A PARTICULAR PURPOSE. |
|
11 ############################################################################## |
|
12 """Datetime interfaces. |
|
13 |
|
14 This module is called idatetime because if it were called datetime the import |
|
15 of the real datetime would fail. |
|
16 """ |
|
17 |
|
18 from zope.interface import Interface, Attribute |
|
19 from zope.interface import classImplements |
|
20 |
|
21 from datetime import timedelta, date, datetime, time, tzinfo |
|
22 |
|
23 |
|
24 class ITimeDeltaClass(Interface): |
|
25 """This is the timedelta class interface.""" |
|
26 |
|
27 min = Attribute("The most negative timedelta object") |
|
28 |
|
29 max = Attribute("The most positive timedelta object") |
|
30 |
|
31 resolution = Attribute( |
|
32 "The smallest difference between non-equal timedelta objects") |
|
33 |
|
34 |
|
35 class ITimeDelta(ITimeDeltaClass): |
|
36 """Represent the difference between two datetime objects. |
|
37 |
|
38 Supported operators: |
|
39 |
|
40 - add, subtract timedelta |
|
41 - unary plus, minus, abs |
|
42 - compare to timedelta |
|
43 - multiply, divide by int/long |
|
44 |
|
45 In addition, datetime supports subtraction of two datetime objects |
|
46 returning a timedelta, and addition or subtraction of a datetime |
|
47 and a timedelta giving a datetime. |
|
48 |
|
49 Representation: (days, seconds, microseconds). |
|
50 """ |
|
51 |
|
52 days = Attribute("Days between -999999999 and 999999999 inclusive") |
|
53 |
|
54 seconds = Attribute("Seconds between 0 and 86399 inclusive") |
|
55 |
|
56 microseconds = Attribute("Microseconds between 0 and 999999 inclusive") |
|
57 |
|
58 |
|
59 class IDateClass(Interface): |
|
60 """This is the date class interface.""" |
|
61 |
|
62 min = Attribute("The earliest representable date") |
|
63 |
|
64 max = Attribute("The latest representable date") |
|
65 |
|
66 resolution = Attribute( |
|
67 "The smallest difference between non-equal date objects") |
|
68 |
|
69 def today(): |
|
70 """Return the current local time. |
|
71 |
|
72 This is equivalent to date.fromtimestamp(time.time())""" |
|
73 |
|
74 def fromtimestamp(timestamp): |
|
75 """Return the local date from a POSIX timestamp (like time.time()) |
|
76 |
|
77 This may raise ValueError, if the timestamp is out of the range of |
|
78 values supported by the platform C localtime() function. It's common |
|
79 for this to be restricted to years from 1970 through 2038. Note that |
|
80 on non-POSIX systems that include leap seconds in their notion of a |
|
81 timestamp, leap seconds are ignored by fromtimestamp(). |
|
82 """ |
|
83 |
|
84 def fromordinal(ordinal): |
|
85 """Return the date corresponding to the proleptic Gregorian ordinal. |
|
86 |
|
87 January 1 of year 1 has ordinal 1. ValueError is raised unless |
|
88 1 <= ordinal <= date.max.toordinal(). |
|
89 For any date d, date.fromordinal(d.toordinal()) == d. |
|
90 """ |
|
91 |
|
92 |
|
93 class IDate(IDateClass): |
|
94 """Represents a date (year, month and day) in an idealized calendar. |
|
95 |
|
96 Operators: |
|
97 |
|
98 __repr__, __str__ |
|
99 __cmp__, __hash__ |
|
100 __add__, __radd__, __sub__ (add/radd only with timedelta arg) |
|
101 """ |
|
102 |
|
103 year = Attribute("Between MINYEAR and MAXYEAR inclusive.") |
|
104 |
|
105 month = Attribute("Between 1 and 12 inclusive") |
|
106 |
|
107 day = Attribute( |
|
108 "Between 1 and the number of days in the given month of the given year.") |
|
109 |
|
110 def replace(year, month, day): |
|
111 """Return a date with the same value. |
|
112 |
|
113 Except for those members given new values by whichever keyword |
|
114 arguments are specified. For example, if d == date(2002, 12, 31), then |
|
115 d.replace(day=26) == date(2000, 12, 26). |
|
116 """ |
|
117 |
|
118 def timetuple(): |
|
119 """Return a 9-element tuple of the form returned by time.localtime(). |
|
120 |
|
121 The hours, minutes and seconds are 0, and the DST flag is -1. |
|
122 d.timetuple() is equivalent to |
|
123 (d.year, d.month, d.day, 0, 0, 0, d.weekday(), d.toordinal() - |
|
124 date(d.year, 1, 1).toordinal() + 1, -1) |
|
125 """ |
|
126 |
|
127 def toordinal(): |
|
128 """Return the proleptic Gregorian ordinal of the date |
|
129 |
|
130 January 1 of year 1 has ordinal 1. For any date object d, |
|
131 date.fromordinal(d.toordinal()) == d. |
|
132 """ |
|
133 |
|
134 def weekday(): |
|
135 """Return the day of the week as an integer. |
|
136 |
|
137 Monday is 0 and Sunday is 6. For example, |
|
138 date(2002, 12, 4).weekday() == 2, a Wednesday. |
|
139 |
|
140 See also isoweekday(). |
|
141 """ |
|
142 |
|
143 def isoweekday(): |
|
144 """Return the day of the week as an integer. |
|
145 |
|
146 Monday is 1 and Sunday is 7. For example, |
|
147 date(2002, 12, 4).isoweekday() == 3, a Wednesday. |
|
148 |
|
149 See also weekday(), isocalendar(). |
|
150 """ |
|
151 |
|
152 def isocalendar(): |
|
153 """Return a 3-tuple, (ISO year, ISO week number, ISO weekday). |
|
154 |
|
155 The ISO calendar is a widely used variant of the Gregorian calendar. |
|
156 See http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for a good |
|
157 explanation. |
|
158 |
|
159 The ISO year consists of 52 or 53 full weeks, and where a week starts |
|
160 on a Monday and ends on a Sunday. The first week of an ISO year is the |
|
161 first (Gregorian) calendar week of a year containing a Thursday. This |
|
162 is called week number 1, and the ISO year of that Thursday is the same |
|
163 as its Gregorian year. |
|
164 |
|
165 For example, 2004 begins on a Thursday, so the first week of ISO year |
|
166 2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004, so |
|
167 that date(2003, 12, 29).isocalendar() == (2004, 1, 1) and |
|
168 date(2004, 1, 4).isocalendar() == (2004, 1, 7). |
|
169 """ |
|
170 |
|
171 def isoformat(): |
|
172 """Return a string representing the date in ISO 8601 format. |
|
173 |
|
174 This is 'YYYY-MM-DD'. |
|
175 For example, date(2002, 12, 4).isoformat() == '2002-12-04'. |
|
176 """ |
|
177 |
|
178 def __str__(): |
|
179 """For a date d, str(d) is equivalent to d.isoformat().""" |
|
180 |
|
181 def ctime(): |
|
182 """Return a string representing the date. |
|
183 |
|
184 For example date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'. |
|
185 d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) |
|
186 on platforms where the native C ctime() function |
|
187 (which time.ctime() invokes, but which date.ctime() does not invoke) |
|
188 conforms to the C standard. |
|
189 """ |
|
190 |
|
191 def strftime(format): |
|
192 """Return a string representing the date. |
|
193 |
|
194 Controlled by an explicit format string. Format codes referring to |
|
195 hours, minutes or seconds will see 0 values. |
|
196 """ |
|
197 |
|
198 |
|
199 class IDateTimeClass(Interface): |
|
200 """This is the datetime class interface.""" |
|
201 |
|
202 min = Attribute("The earliest representable datetime") |
|
203 |
|
204 max = Attribute("The latest representable datetime") |
|
205 |
|
206 resolution = Attribute( |
|
207 "The smallest possible difference between non-equal datetime objects") |
|
208 |
|
209 def today(): |
|
210 """Return the current local datetime, with tzinfo None. |
|
211 |
|
212 This is equivalent to datetime.fromtimestamp(time.time()). |
|
213 See also now(), fromtimestamp(). |
|
214 """ |
|
215 |
|
216 def now(tz=None): |
|
217 """Return the current local date and time. |
|
218 |
|
219 If optional argument tz is None or not specified, this is like today(), |
|
220 but, if possible, supplies more precision than can be gotten from going |
|
221 through a time.time() timestamp (for example, this may be possible on |
|
222 platforms supplying the C gettimeofday() function). |
|
223 |
|
224 Else tz must be an instance of a class tzinfo subclass, and the current |
|
225 date and time are converted to tz's time zone. In this case the result |
|
226 is equivalent to tz.fromutc(datetime.utcnow().replace(tzinfo=tz)). |
|
227 |
|
228 See also today(), utcnow(). |
|
229 """ |
|
230 |
|
231 def utcnow(): |
|
232 """Return the current UTC date and time, with tzinfo None. |
|
233 |
|
234 This is like now(), but returns the current UTC date and time, as a |
|
235 naive datetime object. |
|
236 |
|
237 See also now(). |
|
238 """ |
|
239 |
|
240 def fromtimestamp(timestamp, tz=None): |
|
241 """Return the local date and time corresponding to the POSIX timestamp. |
|
242 |
|
243 Same as is returned by time.time(). If optional argument tz is None or |
|
244 not specified, the timestamp is converted to the platform's local date |
|
245 and time, and the returned datetime object is naive. |
|
246 |
|
247 Else tz must be an instance of a class tzinfo subclass, and the |
|
248 timestamp is converted to tz's time zone. In this case the result is |
|
249 equivalent to |
|
250 tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)). |
|
251 |
|
252 fromtimestamp() may raise ValueError, if the timestamp is out of the |
|
253 range of values supported by the platform C localtime() or gmtime() |
|
254 functions. It's common for this to be restricted to years in 1970 |
|
255 through 2038. Note that on non-POSIX systems that include leap seconds |
|
256 in their notion of a timestamp, leap seconds are ignored by |
|
257 fromtimestamp(), and then it's possible to have two timestamps |
|
258 differing by a second that yield identical datetime objects. |
|
259 |
|
260 See also utcfromtimestamp(). |
|
261 """ |
|
262 |
|
263 def utcfromtimestamp(timestamp): |
|
264 """Return the UTC datetime from the POSIX timestamp with tzinfo None. |
|
265 |
|
266 This may raise ValueError, if the timestamp is out of the range of |
|
267 values supported by the platform C gmtime() function. It's common for |
|
268 this to be restricted to years in 1970 through 2038. |
|
269 |
|
270 See also fromtimestamp(). |
|
271 """ |
|
272 |
|
273 def fromordinal(ordinal): |
|
274 """Return the datetime from the proleptic Gregorian ordinal. |
|
275 |
|
276 January 1 of year 1 has ordinal 1. ValueError is raised unless |
|
277 1 <= ordinal <= datetime.max.toordinal(). |
|
278 The hour, minute, second and microsecond of the result are all 0, and |
|
279 tzinfo is None. |
|
280 """ |
|
281 |
|
282 def combine(date, time): |
|
283 """Return a new datetime object. |
|
284 |
|
285 Its date members are equal to the given date object's, and whose time |
|
286 and tzinfo members are equal to the given time object's. For any |
|
287 datetime object d, d == datetime.combine(d.date(), d.timetz()). |
|
288 If date is a datetime object, its time and tzinfo members are ignored. |
|
289 """ |
|
290 |
|
291 |
|
292 class IDateTime(IDate, IDateTimeClass): |
|
293 """Object contains all the information from a date object and a time object. |
|
294 """ |
|
295 |
|
296 year = Attribute("Year between MINYEAR and MAXYEAR inclusive") |
|
297 |
|
298 month = Attribute("Month between 1 and 12 inclusive") |
|
299 |
|
300 day = Attribute( |
|
301 "Day between 1 and the number of days in the given month of the year") |
|
302 |
|
303 hour = Attribute("Hour in range(24)") |
|
304 |
|
305 minute = Attribute("Minute in range(60)") |
|
306 |
|
307 second = Attribute("Second in range(60)") |
|
308 |
|
309 microsecond = Attribute("Microsecond in range(1000000)") |
|
310 |
|
311 tzinfo = Attribute( |
|
312 """The object passed as the tzinfo argument to the datetime constructor |
|
313 or None if none was passed""") |
|
314 |
|
315 def date(): |
|
316 """Return date object with same year, month and day.""" |
|
317 |
|
318 def time(): |
|
319 """Return time object with same hour, minute, second, microsecond. |
|
320 |
|
321 tzinfo is None. See also method timetz(). |
|
322 """ |
|
323 |
|
324 def timetz(): |
|
325 """Return time object with same hour, minute, second, microsecond, |
|
326 and tzinfo. |
|
327 |
|
328 See also method time(). |
|
329 """ |
|
330 |
|
331 def replace(year, month, day, hour, minute, second, microsecond, tzinfo): |
|
332 """Return a datetime with the same members, except for those members |
|
333 given new values by whichever keyword arguments are specified. |
|
334 |
|
335 Note that tzinfo=None can be specified to create a naive datetime from |
|
336 an aware datetime with no conversion of date and time members. |
|
337 """ |
|
338 |
|
339 def astimezone(tz): |
|
340 """Return a datetime object with new tzinfo member tz, adjusting the |
|
341 date and time members so the result is the same UTC time as self, but |
|
342 in tz's local time. |
|
343 |
|
344 tz must be an instance of a tzinfo subclass, and its utcoffset() and |
|
345 dst() methods must not return None. self must be aware (self.tzinfo |
|
346 must not be None, and self.utcoffset() must not return None). |
|
347 |
|
348 If self.tzinfo is tz, self.astimezone(tz) is equal to self: no |
|
349 adjustment of date or time members is performed. Else the result is |
|
350 local time in time zone tz, representing the same UTC time as self: |
|
351 after astz = dt.astimezone(tz), astz - astz.utcoffset() |
|
352 will usually have the same date and time members as dt - dt.utcoffset(). |
|
353 The discussion of class tzinfo explains the cases at Daylight Saving |
|
354 Time transition boundaries where this cannot be achieved (an issue only |
|
355 if tz models both standard and daylight time). |
|
356 |
|
357 If you merely want to attach a time zone object tz to a datetime dt |
|
358 without adjustment of date and time members, use dt.replace(tzinfo=tz). |
|
359 If you merely want to remove the time zone object from an aware |
|
360 datetime dt without conversion of date and time members, use |
|
361 dt.replace(tzinfo=None). |
|
362 |
|
363 Note that the default tzinfo.fromutc() method can be overridden in a |
|
364 tzinfo subclass to effect the result returned by astimezone(). |
|
365 """ |
|
366 |
|
367 def utcoffset(): |
|
368 """Return the timezone offset in minutes east of UTC (negative west of |
|
369 UTC).""" |
|
370 |
|
371 def dst(): |
|
372 """Return 0 if DST is not in effect, or the DST offset (in minutes |
|
373 eastward) if DST is in effect. |
|
374 """ |
|
375 |
|
376 def tzname(): |
|
377 """Return the timezone name.""" |
|
378 |
|
379 def timetuple(): |
|
380 """Return a 9-element tuple of the form returned by time.localtime().""" |
|
381 |
|
382 def utctimetuple(): |
|
383 """Return UTC time tuple compatilble with time.gmtimr().""" |
|
384 |
|
385 def toordinal(): |
|
386 """Return the proleptic Gregorian ordinal of the date. |
|
387 |
|
388 The same as self.date().toordinal(). |
|
389 """ |
|
390 |
|
391 def weekday(): |
|
392 """Return the day of the week as an integer. |
|
393 |
|
394 Monday is 0 and Sunday is 6. The same as self.date().weekday(). |
|
395 See also isoweekday(). |
|
396 """ |
|
397 |
|
398 def isoweekday(): |
|
399 """Return the day of the week as an integer. |
|
400 |
|
401 Monday is 1 and Sunday is 7. The same as self.date().isoweekday. |
|
402 See also weekday(), isocalendar(). |
|
403 """ |
|
404 |
|
405 def isocalendar(): |
|
406 """Return a 3-tuple, (ISO year, ISO week number, ISO weekday). |
|
407 |
|
408 The same as self.date().isocalendar(). |
|
409 """ |
|
410 |
|
411 def isoformat(sep='T'): |
|
412 """Return a string representing the date and time in ISO 8601 format. |
|
413 |
|
414 YYYY-MM-DDTHH:MM:SS.mmmmmm or YYYY-MM-DDTHH:MM:SS if microsecond is 0 |
|
415 |
|
416 If utcoffset() does not return None, a 6-character string is appended, |
|
417 giving the UTC offset in (signed) hours and minutes: |
|
418 |
|
419 YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or YYYY-MM-DDTHH:MM:SS+HH:MM |
|
420 if microsecond is 0. |
|
421 |
|
422 The optional argument sep (default 'T') is a one-character separator, |
|
423 placed between the date and time portions of the result. |
|
424 """ |
|
425 |
|
426 def __str__(): |
|
427 """For a datetime instance d, str(d) is equivalent to d.isoformat(' '). |
|
428 """ |
|
429 |
|
430 def ctime(): |
|
431 """Return a string representing the date and time. |
|
432 |
|
433 datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'. |
|
434 d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) on |
|
435 platforms where the native C ctime() function (which time.ctime() |
|
436 invokes, but which datetime.ctime() does not invoke) conforms to the |
|
437 C standard. |
|
438 """ |
|
439 |
|
440 def strftime(format): |
|
441 """Return a string representing the date and time. |
|
442 |
|
443 This is controlled by an explicit format string. |
|
444 """ |
|
445 |
|
446 |
|
447 class ITimeClass(Interface): |
|
448 """This is the time class interface.""" |
|
449 |
|
450 min = Attribute("The earliest representable time") |
|
451 |
|
452 max = Attribute("The latest representable time") |
|
453 |
|
454 resolution = Attribute( |
|
455 "The smallest possible difference between non-equal time objects") |
|
456 |
|
457 |
|
458 class ITime(ITimeClass): |
|
459 """Represent time with time zone. |
|
460 |
|
461 Operators: |
|
462 |
|
463 __repr__, __str__ |
|
464 __cmp__, __hash__ |
|
465 """ |
|
466 |
|
467 hour = Attribute("Hour in range(24)") |
|
468 |
|
469 minute = Attribute("Minute in range(60)") |
|
470 |
|
471 second = Attribute("Second in range(60)") |
|
472 |
|
473 microsecond = Attribute("Microsecond in range(1000000)") |
|
474 |
|
475 tzinfo = Attribute( |
|
476 """The object passed as the tzinfo argument to the time constructor |
|
477 or None if none was passed.""") |
|
478 |
|
479 def replace(hour, minute, second, microsecond, tzinfo): |
|
480 """Return a time with the same value. |
|
481 |
|
482 Except for those members given new values by whichever keyword |
|
483 arguments are specified. Note that tzinfo=None can be specified |
|
484 to create a naive time from an aware time, without conversion of the |
|
485 time members. |
|
486 """ |
|
487 |
|
488 def isoformat(): |
|
489 """Return a string representing the time in ISO 8601 format. |
|
490 |
|
491 That is HH:MM:SS.mmmmmm or, if self.microsecond is 0, HH:MM:SS |
|
492 If utcoffset() does not return None, a 6-character string is appended, |
|
493 giving the UTC offset in (signed) hours and minutes: |
|
494 HH:MM:SS.mmmmmm+HH:MM or, if self.microsecond is 0, HH:MM:SS+HH:MM |
|
495 """ |
|
496 |
|
497 def __str__(): |
|
498 """For a time t, str(t) is equivalent to t.isoformat().""" |
|
499 |
|
500 def strftime(format): |
|
501 """Return a string representing the time. |
|
502 |
|
503 This is controlled by an explicit format string. |
|
504 """ |
|
505 |
|
506 def utcoffset(): |
|
507 """Return the timezone offset in minutes east of UTC (negative west of |
|
508 UTC). |
|
509 |
|
510 If tzinfo is None, returns None, else returns |
|
511 self.tzinfo.utcoffset(None), and raises an exception if the latter |
|
512 doesn't return None or a timedelta object representing a whole number |
|
513 of minutes with magnitude less than one day. |
|
514 """ |
|
515 |
|
516 def dst(): |
|
517 """Return 0 if DST is not in effect, or the DST offset (in minutes |
|
518 eastward) if DST is in effect. |
|
519 |
|
520 If tzinfo is None, returns None, else returns self.tzinfo.dst(None), |
|
521 and raises an exception if the latter doesn't return None, or a |
|
522 timedelta object representing a whole number of minutes with |
|
523 magnitude less than one day. |
|
524 """ |
|
525 |
|
526 def tzname(): |
|
527 """Return the timezone name. |
|
528 |
|
529 If tzinfo is None, returns None, else returns self.tzinfo.tzname(None), |
|
530 or raises an exception if the latter doesn't return None or a string |
|
531 object. |
|
532 """ |
|
533 |
|
534 |
|
535 class ITZInfo(Interface): |
|
536 """Time zone info class. |
|
537 """ |
|
538 |
|
539 def utcoffset(dt): |
|
540 """Return offset of local time from UTC, in minutes east of UTC. |
|
541 |
|
542 If local time is west of UTC, this should be negative. |
|
543 Note that this is intended to be the total offset from UTC; |
|
544 for example, if a tzinfo object represents both time zone and DST |
|
545 adjustments, utcoffset() should return their sum. If the UTC offset |
|
546 isn't known, return None. Else the value returned must be a timedelta |
|
547 object specifying a whole number of minutes in the range -1439 to 1439 |
|
548 inclusive (1440 = 24*60; the magnitude of the offset must be less |
|
549 than one day). |
|
550 """ |
|
551 |
|
552 def dst(dt): |
|
553 """Return the daylight saving time (DST) adjustment, in minutes east |
|
554 of UTC, or None if DST information isn't known. |
|
555 """ |
|
556 |
|
557 def tzname(dt): |
|
558 """Return the time zone name corresponding to the datetime object as |
|
559 a string. |
|
560 """ |
|
561 |
|
562 def fromutc(dt): |
|
563 """Return an equivalent datetime in self's local time.""" |
|
564 |
|
565 |
|
566 classImplements(timedelta, ITimeDelta) |
|
567 classImplements(date, IDate) |
|
568 classImplements(datetime, IDateTime) |
|
569 classImplements(time, ITime) |
|
570 classImplements(tzinfo, ITZInfo) |
|
571 |
|
572 ## directlyProvides(timedelta, ITimeDeltaClass) |
|
573 ## directlyProvides(date, IDateClass) |
|
574 ## directlyProvides(datetime, IDateTimeClass) |
|
575 ## directlyProvides(time, ITimeClass) |