1dateutil examples 2================= 3 4.. contents:: 5 6relativedelta examples 7---------------------- 8 9.. testsetup:: relativedelta 10 11 from datetime import *; from dateutil.relativedelta import * 12 import calendar 13 NOW = datetime(2003, 9, 17, 20, 54, 47, 282310) 14 TODAY = date(2003, 9, 17) 15 16Let's begin our trip:: 17 18 >>> from datetime import *; from dateutil.relativedelta import * 19 >>> import calendar 20 21Store some values:: 22 23 >>> NOW = datetime.now() 24 >>> TODAY = date.today() 25 >>> NOW 26 datetime.datetime(2003, 9, 17, 20, 54, 47, 282310) 27 >>> TODAY 28 datetime.date(2003, 9, 17) 29 30Next month 31 32.. doctest:: relativedelta 33 34 >>> NOW+relativedelta(months=+1) 35 datetime.datetime(2003, 10, 17, 20, 54, 47, 282310) 36 37Next month, plus one week. 38 39.. doctest:: relativedelta 40 41 >>> NOW+relativedelta(months=+1, weeks=+1) 42 datetime.datetime(2003, 10, 24, 20, 54, 47, 282310) 43 44Next month, plus one week, at 10am. 45 46.. doctest:: relativedelta 47 48 >>> TODAY+relativedelta(months=+1, weeks=+1, hour=10) 49 datetime.datetime(2003, 10, 24, 10, 0) 50 51Here is another example using an absolute relativedelta. Notice the use of 52year and month (both singular) which causes the values to be *replaced* in the 53original datetime rather than performing an arithmetic operation on them. 54 55.. doctest:: relativedelta 56 57 >>> NOW+relativedelta(year=1, month=1) 58 datetime.datetime(1, 1, 17, 20, 54, 47, 282310) 59 60Let's try the other way around. Notice that the 61hour setting we get in the relativedelta is relative, 62since it's a difference, and the weeks parameter 63has gone. 64 65.. doctest:: relativedelta 66 67 >>> relativedelta(datetime(2003, 10, 24, 10, 0), TODAY) 68 relativedelta(months=+1, days=+7, hours=+10) 69 70One month before one year. 71 72.. doctest:: relativedelta 73 74 >>> NOW+relativedelta(years=+1, months=-1) 75 datetime.datetime(2004, 8, 17, 20, 54, 47, 282310) 76 77How does it handle months with different numbers of days? 78Notice that adding one month will never cross the month 79boundary. 80 81.. doctest:: relativedelta 82 83 >>> date(2003,1,27)+relativedelta(months=+1) 84 datetime.date(2003, 2, 27) 85 >>> date(2003,1,31)+relativedelta(months=+1) 86 datetime.date(2003, 2, 28) 87 >>> date(2003,1,31)+relativedelta(months=+2) 88 datetime.date(2003, 3, 31) 89 90The logic for years is the same, even on leap years. 91 92.. doctest:: relativedelta 93 94 >>> date(2000,2,28)+relativedelta(years=+1) 95 datetime.date(2001, 2, 28) 96 >>> date(2000,2,29)+relativedelta(years=+1) 97 datetime.date(2001, 2, 28) 98 99 >>> date(1999,2,28)+relativedelta(years=+1) 100 datetime.date(2000, 2, 28) 101 >>> date(1999,3,1)+relativedelta(years=+1) 102 datetime.date(2000, 3, 1) 103 104 >>> date(2001,2,28)+relativedelta(years=-1) 105 datetime.date(2000, 2, 28) 106 >>> date(2001,3,1)+relativedelta(years=-1) 107 datetime.date(2000, 3, 1) 108 109Next friday 110 111.. doctest:: relativedelta 112 113 >>> TODAY+relativedelta(weekday=FR) 114 datetime.date(2003, 9, 19) 115 116 >>> TODAY+relativedelta(weekday=calendar.FRIDAY) 117 datetime.date(2003, 9, 19) 118 119Last friday in this month. 120 121.. doctest:: relativedelta 122 123 >>> TODAY+relativedelta(day=31, weekday=FR(-1)) 124 datetime.date(2003, 9, 26) 125 126Next wednesday (it's today!). 127 128.. doctest:: relativedelta 129 130 >>> TODAY+relativedelta(weekday=WE(+1)) 131 datetime.date(2003, 9, 17) 132 133Next wednesday, but not today. 134 135.. doctest:: relativedelta 136 137 >>> TODAY+relativedelta(days=+1, weekday=WE(+1)) 138 datetime.date(2003, 9, 24) 139 140Following 141`ISO year week number notation <https://www.cl.cam.ac.uk/~mgk25/iso-time.html>`_ 142find the first day of the 15th week of 1997. 143 144.. doctest:: relativedelta 145 146 >>> datetime(1997,1,1)+relativedelta(day=4, weekday=MO(-1), weeks=+14) 147 datetime.datetime(1997, 4, 7, 0, 0) 148 149How long ago has the millennium changed? 150 151.. doctest:: relativedelta 152 :options: +NORMALIZE_WHITESPACE 153 154 >>> relativedelta(NOW, date(2001,1,1)) 155 relativedelta(years=+2, months=+8, days=+16, 156 hours=+20, minutes=+54, seconds=+47, microseconds=+282310) 157 158How old is John? 159 160.. doctest:: relativedelta 161 :options: +NORMALIZE_WHITESPACE 162 163 >>> johnbirthday = datetime(1978, 4, 5, 12, 0) 164 >>> relativedelta(NOW, johnbirthday) 165 relativedelta(years=+25, months=+5, days=+12, 166 hours=+8, minutes=+54, seconds=+47, microseconds=+282310) 167 168It works with dates too. 169 170.. doctest:: relativedelta 171 172 >>> relativedelta(TODAY, johnbirthday) 173 relativedelta(years=+25, months=+5, days=+11, hours=+12) 174 175Obtain today's date using the yearday: 176 177.. doctest:: relativedelta 178 179 >>> date(2003, 1, 1)+relativedelta(yearday=260) 180 datetime.date(2003, 9, 17) 181 182We can use today's date, since yearday should be absolute 183in the given year: 184 185.. doctest:: relativedelta 186 187 >>> TODAY+relativedelta(yearday=260) 188 datetime.date(2003, 9, 17) 189 190Last year it should be in the same day: 191 192.. doctest:: relativedelta 193 194 >>> date(2002, 1, 1)+relativedelta(yearday=260) 195 datetime.date(2002, 9, 17) 196 197But not in a leap year: 198 199.. doctest:: relativedelta 200 201 >>> date(2000, 1, 1)+relativedelta(yearday=260) 202 datetime.date(2000, 9, 16) 203 204We can use the non-leap year day to ignore this: 205 206.. doctest:: relativedelta 207 208 >>> date(2000, 1, 1)+relativedelta(nlyearday=260) 209 datetime.date(2000, 9, 17) 210 211rrule examples 212-------------- 213These examples were converted from the RFC. 214 215Prepare the environment. 216 217.. testsetup:: rrule 218 219 from dateutil.rrule import * 220 from dateutil.parser import * 221 from datetime import * 222 import pprint 223 import sys 224 sys.displayhook = pprint.pprint 225 226.. doctest:: rrule 227 228 >>> from dateutil.rrule import * 229 >>> from dateutil.parser import * 230 >>> from datetime import * 231 232 >>> import pprint 233 >>> import sys 234 >>> sys.displayhook = pprint.pprint 235 236Daily, for 10 occurrences. 237 238.. doctest:: rrule 239 :options: +NORMALIZE_WHITESPACE 240 241 >>> list(rrule(DAILY, count=10, 242 ... dtstart=parse("19970902T090000"))) 243 [datetime.datetime(1997, 9, 2, 9, 0), 244 datetime.datetime(1997, 9, 3, 9, 0), 245 datetime.datetime(1997, 9, 4, 9, 0), 246 datetime.datetime(1997, 9, 5, 9, 0), 247 datetime.datetime(1997, 9, 6, 9, 0), 248 datetime.datetime(1997, 9, 7, 9, 0), 249 datetime.datetime(1997, 9, 8, 9, 0), 250 datetime.datetime(1997, 9, 9, 9, 0), 251 datetime.datetime(1997, 9, 10, 9, 0), 252 datetime.datetime(1997, 9, 11, 9, 0)] 253 254Daily until December 24, 1997 255 256.. doctest:: rrule 257 :options: +NORMALIZE_WHITESPACE, +ELLIPSIS 258 259 >>> list(rrule(DAILY, 260 ... dtstart=parse("19970902T090000"), 261 ... until=parse("19971224T000000"))) 262 [datetime.datetime(1997, 9, 2, 9, 0), 263 datetime.datetime(1997, 9, 3, 9, 0), 264 datetime.datetime(1997, 9, 4, 9, 0), 265 ... 266 datetime.datetime(1997, 12, 21, 9, 0), 267 datetime.datetime(1997, 12, 22, 9, 0), 268 datetime.datetime(1997, 12, 23, 9, 0)] 269 270Every other day, 5 occurrences. 271 272.. doctest:: rrule 273 :options: +NORMALIZE_WHITESPACE 274 275 >>> list(rrule(DAILY, interval=2, count=5, 276 ... dtstart=parse("19970902T090000"))) 277 [datetime.datetime(1997, 9, 2, 9, 0), 278 datetime.datetime(1997, 9, 4, 9, 0), 279 datetime.datetime(1997, 9, 6, 9, 0), 280 datetime.datetime(1997, 9, 8, 9, 0), 281 datetime.datetime(1997, 9, 10, 9, 0)] 282 283Every 10 days, 5 occurrences. 284 285.. doctest:: rrule 286 :options: +NORMALIZE_WHITESPACE 287 288 >>> list(rrule(DAILY, interval=10, count=5, 289 ... dtstart=parse("19970902T090000"))) 290 [datetime.datetime(1997, 9, 2, 9, 0), 291 datetime.datetime(1997, 9, 12, 9, 0), 292 datetime.datetime(1997, 9, 22, 9, 0), 293 datetime.datetime(1997, 10, 2, 9, 0), 294 datetime.datetime(1997, 10, 12, 9, 0)] 295 296Everyday in January, for 3 years. 297 298.. doctest:: rrule 299 :options: +NORMALIZE_WHITESPACE, +ELLIPSIS 300 301 >>> list(rrule(YEARLY, bymonth=1, byweekday=range(7), 302 ... dtstart=parse("19980101T090000"), 303 ... until=parse("20000131T090000"))) 304 [datetime.datetime(1998, 1, 1, 9, 0), 305 datetime.datetime(1998, 1, 2, 9, 0), 306 ... 307 datetime.datetime(1998, 1, 30, 9, 0), 308 datetime.datetime(1998, 1, 31, 9, 0), 309 datetime.datetime(1999, 1, 1, 9, 0), 310 datetime.datetime(1999, 1, 2, 9, 0), 311 ... 312 datetime.datetime(1999, 1, 30, 9, 0), 313 datetime.datetime(1999, 1, 31, 9, 0), 314 datetime.datetime(2000, 1, 1, 9, 0), 315 datetime.datetime(2000, 1, 2, 9, 0), 316 ... 317 datetime.datetime(2000, 1, 30, 9, 0), 318 datetime.datetime(2000, 1, 31, 9, 0)] 319 320Same thing, in another way. 321 322.. doctest:: rrule 323 :options: +NORMALIZE_WHITESPACE, +ELLIPSIS 324 325 >>> list(rrule(DAILY, bymonth=1, 326 ... dtstart=parse("19980101T090000"), 327 ... until=parse("20000131T090000"))) 328 [datetime.datetime(1998, 1, 1, 9, 0), 329 ... 330 datetime.datetime(2000, 1, 31, 9, 0)] 331 332Weekly for 10 occurrences. 333 334.. doctest:: rrule 335 :options: +NORMALIZE_WHITESPACE 336 337 >>> list(rrule(WEEKLY, count=10, 338 ... dtstart=parse("19970902T090000"))) 339 [datetime.datetime(1997, 9, 2, 9, 0), 340 datetime.datetime(1997, 9, 9, 9, 0), 341 datetime.datetime(1997, 9, 16, 9, 0), 342 datetime.datetime(1997, 9, 23, 9, 0), 343 datetime.datetime(1997, 9, 30, 9, 0), 344 datetime.datetime(1997, 10, 7, 9, 0), 345 datetime.datetime(1997, 10, 14, 9, 0), 346 datetime.datetime(1997, 10, 21, 9, 0), 347 datetime.datetime(1997, 10, 28, 9, 0), 348 datetime.datetime(1997, 11, 4, 9, 0)] 349 350Every other week, 6 occurrences. 351 352.. doctest:: rrule 353 :options: +NORMALIZE_WHITESPACE 354 355 >>> list(rrule(WEEKLY, interval=2, count=6, 356 ... dtstart=parse("19970902T090000"))) 357 [datetime.datetime(1997, 9, 2, 9, 0), 358 datetime.datetime(1997, 9, 16, 9, 0), 359 datetime.datetime(1997, 9, 30, 9, 0), 360 datetime.datetime(1997, 10, 14, 9, 0), 361 datetime.datetime(1997, 10, 28, 9, 0), 362 datetime.datetime(1997, 11, 11, 9, 0)] 363 364Weekly on Tuesday and Thursday for 5 weeks. 365 366.. doctest:: rrule 367 :options: +NORMALIZE_WHITESPACE 368 369 >>> list(rrule(WEEKLY, count=10, wkst=SU, byweekday=(TU,TH), 370 ... dtstart=parse("19970902T090000"))) 371 [datetime.datetime(1997, 9, 2, 9, 0), 372 datetime.datetime(1997, 9, 4, 9, 0), 373 datetime.datetime(1997, 9, 9, 9, 0), 374 datetime.datetime(1997, 9, 11, 9, 0), 375 datetime.datetime(1997, 9, 16, 9, 0), 376 datetime.datetime(1997, 9, 18, 9, 0), 377 datetime.datetime(1997, 9, 23, 9, 0), 378 datetime.datetime(1997, 9, 25, 9, 0), 379 datetime.datetime(1997, 9, 30, 9, 0), 380 datetime.datetime(1997, 10, 2, 9, 0)] 381 382Every other week on Tuesday and Thursday, for 8 occurrences. 383 384.. doctest:: rrule 385 :options: +NORMALIZE_WHITESPACE 386 387 >>> list(rrule(WEEKLY, interval=2, count=8, 388 ... wkst=SU, byweekday=(TU,TH), 389 ... dtstart=parse("19970902T090000"))) 390 [datetime.datetime(1997, 9, 2, 9, 0), 391 datetime.datetime(1997, 9, 4, 9, 0), 392 datetime.datetime(1997, 9, 16, 9, 0), 393 datetime.datetime(1997, 9, 18, 9, 0), 394 datetime.datetime(1997, 9, 30, 9, 0), 395 datetime.datetime(1997, 10, 2, 9, 0), 396 datetime.datetime(1997, 10, 14, 9, 0), 397 datetime.datetime(1997, 10, 16, 9, 0)] 398 399Monthly on the 1st Friday for ten occurrences. 400 401.. doctest:: rrule 402 :options: +NORMALIZE_WHITESPACE 403 404 >>> list(rrule(MONTHLY, count=10, byweekday=FR(1), 405 ... dtstart=parse("19970905T090000"))) 406 [datetime.datetime(1997, 9, 5, 9, 0), 407 datetime.datetime(1997, 10, 3, 9, 0), 408 datetime.datetime(1997, 11, 7, 9, 0), 409 datetime.datetime(1997, 12, 5, 9, 0), 410 datetime.datetime(1998, 1, 2, 9, 0), 411 datetime.datetime(1998, 2, 6, 9, 0), 412 datetime.datetime(1998, 3, 6, 9, 0), 413 datetime.datetime(1998, 4, 3, 9, 0), 414 datetime.datetime(1998, 5, 1, 9, 0), 415 datetime.datetime(1998, 6, 5, 9, 0)] 416 417Every other month on the 1st and last Sunday of the month for 10 occurrences. 418 419.. doctest:: rrule 420 :options: +NORMALIZE_WHITESPACE 421 422 >>> list(rrule(MONTHLY, interval=2, count=10, 423 ... byweekday=(SU(1), SU(-1)), 424 ... dtstart=parse("19970907T090000"))) 425 [datetime.datetime(1997, 9, 7, 9, 0), 426 datetime.datetime(1997, 9, 28, 9, 0), 427 datetime.datetime(1997, 11, 2, 9, 0), 428 datetime.datetime(1997, 11, 30, 9, 0), 429 datetime.datetime(1998, 1, 4, 9, 0), 430 datetime.datetime(1998, 1, 25, 9, 0), 431 datetime.datetime(1998, 3, 1, 9, 0), 432 datetime.datetime(1998, 3, 29, 9, 0), 433 datetime.datetime(1998, 5, 3, 9, 0), 434 datetime.datetime(1998, 5, 31, 9, 0)] 435 436Monthly on the second to last Monday of the month for 6 months. 437 438.. doctest:: rrule 439 :options: +NORMALIZE_WHITESPACE 440 441 >>> list(rrule(MONTHLY, count=6, byweekday=MO(-2), 442 ... dtstart=parse("19970922T090000"))) 443 [datetime.datetime(1997, 9, 22, 9, 0), 444 datetime.datetime(1997, 10, 20, 9, 0), 445 datetime.datetime(1997, 11, 17, 9, 0), 446 datetime.datetime(1997, 12, 22, 9, 0), 447 datetime.datetime(1998, 1, 19, 9, 0), 448 datetime.datetime(1998, 2, 16, 9, 0)] 449 450 451Monthly on the third to the last day of the month, for 6 months. 452 453.. doctest:: rrule 454 :options: +NORMALIZE_WHITESPACE 455 456 >>> list(rrule(MONTHLY, count=6, bymonthday=-3, 457 ... dtstart=parse("19970928T090000"))) 458 [datetime.datetime(1997, 9, 28, 9, 0), 459 datetime.datetime(1997, 10, 29, 9, 0), 460 datetime.datetime(1997, 11, 28, 9, 0), 461 datetime.datetime(1997, 12, 29, 9, 0), 462 datetime.datetime(1998, 1, 29, 9, 0), 463 datetime.datetime(1998, 2, 26, 9, 0)] 464 465 466Monthly on the 2nd and 15th of the month for 5 occurrences. 467 468.. doctest:: rrule 469 :options: +NORMALIZE_WHITESPACE 470 471 >>> list(rrule(MONTHLY, count=5, bymonthday=(2,15), 472 ... dtstart=parse("19970902T090000"))) 473 [datetime.datetime(1997, 9, 2, 9, 0), 474 datetime.datetime(1997, 9, 15, 9, 0), 475 datetime.datetime(1997, 10, 2, 9, 0), 476 datetime.datetime(1997, 10, 15, 9, 0), 477 datetime.datetime(1997, 11, 2, 9, 0)] 478 479 480Monthly on the first and last day of the month for 3 occurrences. 481 482.. doctest:: rrule 483 :options: +NORMALIZE_WHITESPACE 484 485 >>> list(rrule(MONTHLY, count=5, bymonthday=(-1,1,), 486 ... dtstart=parse("19970902T090000"))) 487 [datetime.datetime(1997, 9, 30, 9, 0), 488 datetime.datetime(1997, 10, 1, 9, 0), 489 datetime.datetime(1997, 10, 31, 9, 0), 490 datetime.datetime(1997, 11, 1, 9, 0), 491 datetime.datetime(1997, 11, 30, 9, 0)] 492 493 494Every 18 months on the 10th thru 15th of the month for 10 occurrences. 495 496.. doctest:: rrule 497 :options: +NORMALIZE_WHITESPACE 498 499 >>> list(rrule(MONTHLY, interval=18, count=10, 500 ... bymonthday=range(10,16), 501 ... dtstart=parse("19970910T090000"))) 502 [datetime.datetime(1997, 9, 10, 9, 0), 503 datetime.datetime(1997, 9, 11, 9, 0), 504 datetime.datetime(1997, 9, 12, 9, 0), 505 datetime.datetime(1997, 9, 13, 9, 0), 506 datetime.datetime(1997, 9, 14, 9, 0), 507 datetime.datetime(1997, 9, 15, 9, 0), 508 datetime.datetime(1999, 3, 10, 9, 0), 509 datetime.datetime(1999, 3, 11, 9, 0), 510 datetime.datetime(1999, 3, 12, 9, 0), 511 datetime.datetime(1999, 3, 13, 9, 0)] 512 513 514Every Tuesday, every other month, 6 occurences. 515 516.. doctest:: rrule 517 :options: +NORMALIZE_WHITESPACE 518 519 >>> list(rrule(MONTHLY, interval=2, count=6, byweekday=TU, 520 ... dtstart=parse("19970902T090000"))) 521 [datetime.datetime(1997, 9, 2, 9, 0), 522 datetime.datetime(1997, 9, 9, 9, 0), 523 datetime.datetime(1997, 9, 16, 9, 0), 524 datetime.datetime(1997, 9, 23, 9, 0), 525 datetime.datetime(1997, 9, 30, 9, 0), 526 datetime.datetime(1997, 11, 4, 9, 0)] 527 528 529Yearly in June and July for 10 occurrences. 530 531.. doctest:: rrule 532 :options: +NORMALIZE_WHITESPACE 533 534 >>> list(rrule(YEARLY, count=4, bymonth=(6,7), 535 ... dtstart=parse("19970610T090000"))) 536 [datetime.datetime(1997, 6, 10, 9, 0), 537 datetime.datetime(1997, 7, 10, 9, 0), 538 datetime.datetime(1998, 6, 10, 9, 0), 539 datetime.datetime(1998, 7, 10, 9, 0)] 540 541 542Every 3rd year on the 1st, 100th and 200th day for 4 occurrences. 543 544.. doctest:: rrule 545 :options: +NORMALIZE_WHITESPACE 546 547 >>> list(rrule(YEARLY, count=4, interval=3, byyearday=(1,100,200), 548 ... dtstart=parse("19970101T090000"))) 549 [datetime.datetime(1997, 1, 1, 9, 0), 550 datetime.datetime(1997, 4, 10, 9, 0), 551 datetime.datetime(1997, 7, 19, 9, 0), 552 datetime.datetime(2000, 1, 1, 9, 0)] 553 554 555Every 20th Monday of the year, 3 occurrences. 556 557.. doctest:: rrule 558 :options: +NORMALIZE_WHITESPACE 559 560 >>> list(rrule(YEARLY, count=3, byweekday=MO(20), 561 ... dtstart=parse("19970519T090000"))) 562 [datetime.datetime(1997, 5, 19, 9, 0), 563 datetime.datetime(1998, 5, 18, 9, 0), 564 datetime.datetime(1999, 5, 17, 9, 0)] 565 566 567Monday of week number 20 (where the default start of the week is Monday), 5683 occurrences. 569 570.. doctest:: rrule 571 :options: +NORMALIZE_WHITESPACE 572 573 >>> list(rrule(YEARLY, count=3, byweekno=20, byweekday=MO, 574 ... dtstart=parse("19970512T090000"))) 575 [datetime.datetime(1997, 5, 12, 9, 0), 576 datetime.datetime(1998, 5, 11, 9, 0), 577 datetime.datetime(1999, 5, 17, 9, 0)] 578 579 580The week number 1 may be in the last year. 581 582.. doctest:: rrule 583 :options: +NORMALIZE_WHITESPACE 584 585 >>> list(rrule(WEEKLY, count=3, byweekno=1, byweekday=MO, 586 ... dtstart=parse("19970902T090000"))) 587 [datetime.datetime(1997, 12, 29, 9, 0), 588 datetime.datetime(1999, 1, 4, 9, 0), 589 datetime.datetime(2000, 1, 3, 9, 0)] 590 591 592And the week numbers greater than 51 may be in the next year. 593 594.. doctest:: rrule 595 :options: +NORMALIZE_WHITESPACE 596 597 >>> list(rrule(WEEKLY, count=3, byweekno=52, byweekday=SU, 598 ... dtstart=parse("19970902T090000"))) 599 [datetime.datetime(1997, 12, 28, 9, 0), 600 datetime.datetime(1998, 12, 27, 9, 0), 601 datetime.datetime(2000, 1, 2, 9, 0)] 602 603 604Only some years have week number 53: 605 606.. doctest:: rrule 607 :options: +NORMALIZE_WHITESPACE 608 609 >>> list(rrule(WEEKLY, count=3, byweekno=53, byweekday=MO, 610 ... dtstart=parse("19970902T090000"))) 611 [datetime.datetime(1998, 12, 28, 9, 0), 612 datetime.datetime(2004, 12, 27, 9, 0), 613 datetime.datetime(2009, 12, 28, 9, 0)] 614 615 616Every Friday the 13th, 4 occurrences. 617 618.. doctest:: rrule 619 :options: +NORMALIZE_WHITESPACE 620 621 >>> list(rrule(YEARLY, count=4, byweekday=FR, bymonthday=13, 622 ... dtstart=parse("19970902T090000"))) 623 [datetime.datetime(1998, 2, 13, 9, 0), 624 datetime.datetime(1998, 3, 13, 9, 0), 625 datetime.datetime(1998, 11, 13, 9, 0), 626 datetime.datetime(1999, 8, 13, 9, 0)] 627 628 629Every four years, the first Tuesday after a Monday in November, 6303 occurrences (U.S. Presidential Election day): 631 632.. doctest:: rrule 633 :options: +NORMALIZE_WHITESPACE 634 635 >>> list(rrule(YEARLY, interval=4, count=3, bymonth=11, 636 ... byweekday=TU, bymonthday=(2,3,4,5,6,7,8), 637 ... dtstart=parse("19961105T090000"))) 638 [datetime.datetime(1996, 11, 5, 9, 0), 639 datetime.datetime(2000, 11, 7, 9, 0), 640 datetime.datetime(2004, 11, 2, 9, 0)] 641 642 643The 3rd instance into the month of one of Tuesday, Wednesday or 644Thursday, for the next 3 months: 645 646.. doctest:: rrule 647 :options: +NORMALIZE_WHITESPACE 648 649 >>> list(rrule(MONTHLY, count=3, byweekday=(TU,WE,TH), 650 ... bysetpos=3, dtstart=parse("19970904T090000"))) 651 [datetime.datetime(1997, 9, 4, 9, 0), 652 datetime.datetime(1997, 10, 7, 9, 0), 653 datetime.datetime(1997, 11, 6, 9, 0)] 654 655 656The 2nd to last weekday of the month, 3 occurrences. 657 658.. doctest:: rrule 659 :options: +NORMALIZE_WHITESPACE 660 661 >>> list(rrule(MONTHLY, count=3, byweekday=(MO,TU,WE,TH,FR), 662 ... bysetpos=-2, dtstart=parse("19970929T090000"))) 663 [datetime.datetime(1997, 9, 29, 9, 0), 664 datetime.datetime(1997, 10, 30, 9, 0), 665 datetime.datetime(1997, 11, 27, 9, 0)] 666 667 668Every 3 hours from 9:00 AM to 5:00 PM on a specific day. 669 670.. doctest:: rrule 671 :options: +NORMALIZE_WHITESPACE 672 673 >>> list(rrule(HOURLY, interval=3, 674 ... dtstart=parse("19970902T090000"), 675 ... until=parse("19970902T170000"))) 676 [datetime.datetime(1997, 9, 2, 9, 0), 677 datetime.datetime(1997, 9, 2, 12, 0), 678 datetime.datetime(1997, 9, 2, 15, 0)] 679 680 681Every 15 minutes for 6 occurrences. 682 683.. doctest:: rrule 684 :options: +NORMALIZE_WHITESPACE 685 686 >>> list(rrule(MINUTELY, interval=15, count=6, 687 ... dtstart=parse("19970902T090000"))) 688 [datetime.datetime(1997, 9, 2, 9, 0), 689 datetime.datetime(1997, 9, 2, 9, 15), 690 datetime.datetime(1997, 9, 2, 9, 30), 691 datetime.datetime(1997, 9, 2, 9, 45), 692 datetime.datetime(1997, 9, 2, 10, 0), 693 datetime.datetime(1997, 9, 2, 10, 15)] 694 695 696Every hour and a half for 4 occurrences. 697 698.. doctest:: rrule 699 :options: +NORMALIZE_WHITESPACE 700 701 >>> list(rrule(MINUTELY, interval=90, count=4, 702 ... dtstart=parse("19970902T090000"))) 703 [datetime.datetime(1997, 9, 2, 9, 0), 704 datetime.datetime(1997, 9, 2, 10, 30), 705 datetime.datetime(1997, 9, 2, 12, 0), 706 datetime.datetime(1997, 9, 2, 13, 30)] 707 708 709Every 20 minutes from 9:00 AM to 4:40 PM for two days. 710 711.. doctest:: rrule 712 :options: +NORMALIZE_WHITESPACE, +ELLIPSIS 713 714 >>> list(rrule(MINUTELY, interval=20, count=48, 715 ... byhour=range(9,17), byminute=(0,20,40), 716 ... dtstart=parse("19970902T090000"))) 717 [datetime.datetime(1997, 9, 2, 9, 0), 718 datetime.datetime(1997, 9, 2, 9, 20), 719 ... 720 datetime.datetime(1997, 9, 2, 16, 20), 721 datetime.datetime(1997, 9, 2, 16, 40), 722 datetime.datetime(1997, 9, 3, 9, 0), 723 datetime.datetime(1997, 9, 3, 9, 20), 724 ... 725 datetime.datetime(1997, 9, 3, 16, 20), 726 datetime.datetime(1997, 9, 3, 16, 40)] 727 728 729An example where the days generated makes a difference because of `wkst`. 730 731.. doctest:: rrule 732 :options: +NORMALIZE_WHITESPACE 733 734 >>> list(rrule(WEEKLY, interval=2, count=4, 735 ... byweekday=(TU,SU), wkst=MO, 736 ... dtstart=parse("19970805T090000"))) 737 [datetime.datetime(1997, 8, 5, 9, 0), 738 datetime.datetime(1997, 8, 10, 9, 0), 739 datetime.datetime(1997, 8, 19, 9, 0), 740 datetime.datetime(1997, 8, 24, 9, 0)] 741 742 >>> list(rrule(WEEKLY, interval=2, count=4, 743 ... byweekday=(TU,SU), wkst=SU, 744 ... dtstart=parse("19970805T090000"))) 745 [datetime.datetime(1997, 8, 5, 9, 0), 746 datetime.datetime(1997, 8, 17, 9, 0), 747 datetime.datetime(1997, 8, 19, 9, 0), 748 datetime.datetime(1997, 8, 31, 9, 0)] 749 750 751rruleset examples 752----------------- 753Daily, for 7 days, jumping Saturday and Sunday occurrences. 754 755.. testsetup:: rruleset 756 757 import datetime 758 759 from dateutil.parser import parse 760 from dateutil.rrule import rrule, rruleset 761 from dateutil.rrule import YEARLY, MONTHLY, WEEKLY, DAILY 762 from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU 763 764 import pprint 765 import sys 766 sys.displayhook = pprint.pprint 767 768.. doctest:: rruleset 769 :options: +NORMALIZE_WHITESPACE 770 771 >>> set = rruleset() 772 >>> set.rrule(rrule(DAILY, count=7, 773 ... dtstart=parse("19970902T090000"))) 774 >>> set.exrule(rrule(YEARLY, byweekday=(SA,SU), 775 ... dtstart=parse("19970902T090000"))) 776 >>> list(set) 777 [datetime.datetime(1997, 9, 2, 9, 0), 778 datetime.datetime(1997, 9, 3, 9, 0), 779 datetime.datetime(1997, 9, 4, 9, 0), 780 datetime.datetime(1997, 9, 5, 9, 0), 781 datetime.datetime(1997, 9, 8, 9, 0)] 782 783 784Weekly, for 4 weeks, plus one time on day 7, and not on day 16. 785 786.. doctest:: rruleset 787 :options: +NORMALIZE_WHITESPACE 788 789 >>> set = rruleset() 790 >>> set.rrule(rrule(WEEKLY, count=4, 791 ... dtstart=parse("19970902T090000"))) 792 >>> set.rdate(datetime.datetime(1997, 9, 7, 9, 0)) 793 >>> set.exdate(datetime.datetime(1997, 9, 16, 9, 0)) 794 >>> list(set) 795 [datetime.datetime(1997, 9, 2, 9, 0), 796 datetime.datetime(1997, 9, 7, 9, 0), 797 datetime.datetime(1997, 9, 9, 9, 0), 798 datetime.datetime(1997, 9, 23, 9, 0)] 799 800 801rrulestr() examples 802------------------- 803 804Every 10 days, 5 occurrences. 805 806.. testsetup:: rrulestr 807 808 from dateutil.parser import parse 809 from dateutil.rrule import rruleset, rrulestr 810 811 import pprint 812 import sys 813 sys.displayhook = pprint.pprint 814 815.. doctest:: rrulestr 816 :options: +NORMALIZE_WHITESPACE 817 818 >>> list(rrulestr(""" 819 ... DTSTART:19970902T090000 820 ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5 821 ... """)) 822 [datetime.datetime(1997, 9, 2, 9, 0), 823 datetime.datetime(1997, 9, 12, 9, 0), 824 datetime.datetime(1997, 9, 22, 9, 0), 825 datetime.datetime(1997, 10, 2, 9, 0), 826 datetime.datetime(1997, 10, 12, 9, 0)] 827 828 829Same thing, but passing only the `RRULE` value. 830 831.. doctest:: rrulestr 832 :options: +NORMALIZE_WHITESPACE 833 834 >>> list(rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5", 835 ... dtstart=parse("19970902T090000"))) 836 [datetime.datetime(1997, 9, 2, 9, 0), 837 datetime.datetime(1997, 9, 12, 9, 0), 838 datetime.datetime(1997, 9, 22, 9, 0), 839 datetime.datetime(1997, 10, 2, 9, 0), 840 datetime.datetime(1997, 10, 12, 9, 0)] 841 842 843Notice that when using a single rule, it returns an 844`rrule` instance, unless `forceset` was used. 845 846.. doctest:: rrulestr 847 :options: +ELLIPSIS 848 849 >>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5") 850 <dateutil.rrule.rrule object at 0x...> 851 852 >>> rrulestr(""" 853 ... DTSTART:19970902T090000 854 ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5 855 ... """) 856 <dateutil.rrule.rrule object at 0x...> 857 858 >>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5", forceset=True) 859 <dateutil.rrule.rruleset object at 0x...> 860 861 862But when an `rruleset` is needed, it is automatically used. 863 864.. doctest:: rrulestr 865 :options: +ELLIPSIS 866 867 >>> rrulestr(""" 868 ... DTSTART:19970902T090000 869 ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5 870 ... RRULE:FREQ=DAILY;INTERVAL=5;COUNT=3 871 ... """) 872 <dateutil.rrule.rruleset object at 0x...> 873 874 875parse examples 876-------------- 877The following code will prepare the environment: 878 879.. doctest:: tz 880 881 >>> from dateutil.parser import * 882 >>> from dateutil.tz import * 883 >>> from datetime import * 884 >>> TZOFFSETS = {"BRST": -10800} 885 >>> BRSTTZ = tzoffset("BRST", -10800) 886 >>> DEFAULT = datetime(2003, 9, 25) 887 888 889Some simple examples based on the `date` command, using the 890`ZOFFSET` dictionary to provide the BRST timezone offset. 891 892.. doctest:: tz 893 :options: +NORMALIZE_WHITESPACE 894 895 >>> parse("Thu Sep 25 10:36:28 BRST 2003", tzinfos=TZOFFSETS) 896 datetime.datetime(2003, 9, 25, 10, 36, 28, 897 tzinfo=tzoffset('BRST', -10800)) 898 899 >>> parse("2003 10:36:28 BRST 25 Sep Thu", tzinfos=TZOFFSETS) 900 datetime.datetime(2003, 9, 25, 10, 36, 28, 901 tzinfo=tzoffset('BRST', -10800)) 902 903 904Notice that since BRST is my local timezone, parsing it without 905further timezone settings will yield a `tzlocal` timezone. 906 907.. doctest:: tz 908 909 >>> parse("Thu Sep 25 10:36:28 BRST 2003") 910 datetime.datetime(2003, 9, 25, 10, 36, 28, tzinfo=tzlocal()) 911 912 913We can also ask to ignore the timezone explicitly: 914 915.. doctest:: tz 916 917 >>> parse("Thu Sep 25 10:36:28 BRST 2003", ignoretz=True) 918 datetime.datetime(2003, 9, 25, 10, 36, 28) 919 920 921That's the same as processing a string without timezone: 922 923.. doctest:: tz 924 925 >>> parse("Thu Sep 25 10:36:28 2003") 926 datetime.datetime(2003, 9, 25, 10, 36, 28) 927 928 929Without the year, but passing our `DEFAULT` datetime to return 930the same year, no mattering what year we currently are in: 931 932.. doctest:: tz 933 934 >>> parse("Thu Sep 25 10:36:28", default=DEFAULT) 935 datetime.datetime(2003, 9, 25, 10, 36, 28) 936 937 938Strip it further: 939 940.. doctest:: tz 941 942 >>> parse("Thu Sep 10:36:28", default=DEFAULT) 943 datetime.datetime(2003, 9, 25, 10, 36, 28) 944 945 >>> parse("Thu 10:36:28", default=DEFAULT) 946 datetime.datetime(2003, 9, 25, 10, 36, 28) 947 948 >>> parse("Thu 10:36", default=DEFAULT) 949 datetime.datetime(2003, 9, 25, 10, 36) 950 951 >>> parse("10:36", default=DEFAULT) 952 datetime.datetime(2003, 9, 25, 10, 36) 953 954 955Strip in a different way: 956 957.. doctest:: tz 958 959 >>> parse("Thu Sep 25 2003") 960 datetime.datetime(2003, 9, 25, 0, 0) 961 962 >>> parse("Sep 25 2003") 963 datetime.datetime(2003, 9, 25, 0, 0) 964 965 >>> parse("Sep 2003", default=DEFAULT) 966 datetime.datetime(2003, 9, 25, 0, 0) 967 968 >>> parse("Sep", default=DEFAULT) 969 datetime.datetime(2003, 9, 25, 0, 0) 970 971 >>> parse("2003", default=DEFAULT) 972 datetime.datetime(2003, 9, 25, 0, 0) 973 974 975Another format, based on `date -R` (RFC822): 976 977.. doctest:: tz 978 :options: +NORMALIZE_WHITESPACE 979 980 >>> parse("Thu, 25 Sep 2003 10:49:41 -0300") 981 datetime.datetime(2003, 9, 25, 10, 49, 41, 982 tzinfo=tzoffset(None, -10800)) 983 984 985ISO format: 986 987.. doctest:: tz 988 :options: +NORMALIZE_WHITESPACE 989 990 >>> parse("2003-09-25T10:49:41.5-03:00") 991 datetime.datetime(2003, 9, 25, 10, 49, 41, 500000, 992 tzinfo=tzoffset(None, -10800)) 993 994 995Some variations: 996 997.. doctest:: tz 998 999 >>> parse("2003-09-25T10:49:41") 1000 datetime.datetime(2003, 9, 25, 10, 49, 41) 1001 1002 >>> parse("2003-09-25T10:49") 1003 datetime.datetime(2003, 9, 25, 10, 49) 1004 1005 >>> parse("2003-09-25T10") 1006 datetime.datetime(2003, 9, 25, 10, 0) 1007 1008 >>> parse("2003-09-25") 1009 datetime.datetime(2003, 9, 25, 0, 0) 1010 1011 1012ISO format, without separators: 1013 1014.. doctest:: tz 1015 :options: +NORMALIZE_WHITESPACE 1016 1017 >>> parse("20030925T104941.5-0300") 1018 datetime.datetime(2003, 9, 25, 10, 49, 41, 500000, 1019 tzinfo=tzoffset(None, -10800)) 1020 1021 >>> parse("20030925T104941-0300") 1022 datetime.datetime(2003, 9, 25, 10, 49, 41, 1023 tzinfo=tzoffset(None, -10800)) 1024 1025 >>> parse("20030925T104941") 1026 datetime.datetime(2003, 9, 25, 10, 49, 41) 1027 1028 >>> parse("20030925T1049") 1029 datetime.datetime(2003, 9, 25, 10, 49) 1030 1031 >>> parse("20030925T10") 1032 datetime.datetime(2003, 9, 25, 10, 0) 1033 1034 >>> parse("20030925") 1035 datetime.datetime(2003, 9, 25, 0, 0) 1036 1037 1038Everything together. 1039 1040.. doctest:: tz 1041 1042 >>> parse("199709020900") 1043 datetime.datetime(1997, 9, 2, 9, 0) 1044 >>> parse("19970902090059") 1045 datetime.datetime(1997, 9, 2, 9, 0, 59) 1046 1047 1048Different date orderings: 1049 1050.. doctest:: tz 1051 1052 >>> parse("2003-09-25") 1053 datetime.datetime(2003, 9, 25, 0, 0) 1054 1055 >>> parse("2003-Sep-25") 1056 datetime.datetime(2003, 9, 25, 0, 0) 1057 1058 >>> parse("25-Sep-2003") 1059 datetime.datetime(2003, 9, 25, 0, 0) 1060 1061 >>> parse("Sep-25-2003") 1062 datetime.datetime(2003, 9, 25, 0, 0) 1063 1064 >>> parse("09-25-2003") 1065 datetime.datetime(2003, 9, 25, 0, 0) 1066 1067 >>> parse("25-09-2003") 1068 datetime.datetime(2003, 9, 25, 0, 0) 1069 1070 1071Check some ambiguous dates: 1072 1073.. doctest:: tz 1074 1075 >>> parse("10-09-2003") 1076 datetime.datetime(2003, 10, 9, 0, 0) 1077 1078 >>> parse("10-09-2003", dayfirst=True) 1079 datetime.datetime(2003, 9, 10, 0, 0) 1080 1081 >>> parse("10-09-03") 1082 datetime.datetime(2003, 10, 9, 0, 0) 1083 1084 >>> parse("10-09-03", yearfirst=True) 1085 datetime.datetime(2010, 9, 3, 0, 0) 1086 1087 1088Other date separators are allowed: 1089 1090.. doctest:: tz 1091 1092 >>> parse("2003.Sep.25") 1093 datetime.datetime(2003, 9, 25, 0, 0) 1094 1095 >>> parse("2003/09/25") 1096 datetime.datetime(2003, 9, 25, 0, 0) 1097 1098 1099Even with spaces: 1100 1101.. doctest:: tz 1102 1103 >>> parse("2003 Sep 25") 1104 datetime.datetime(2003, 9, 25, 0, 0) 1105 1106 >>> parse("2003 09 25") 1107 datetime.datetime(2003, 9, 25, 0, 0) 1108 1109 1110Hours with letters work: 1111 1112.. doctest:: tz 1113 1114 >>> parse("10h36m28.5s", default=DEFAULT) 1115 datetime.datetime(2003, 9, 25, 10, 36, 28, 500000) 1116 1117 >>> parse("01s02h03m", default=DEFAULT) 1118 datetime.datetime(2003, 9, 25, 2, 3, 1) 1119 1120 >>> parse("01h02m03", default=DEFAULT) 1121 datetime.datetime(2003, 9, 25, 1, 2, 3) 1122 1123 >>> parse("01h02", default=DEFAULT) 1124 datetime.datetime(2003, 9, 25, 1, 2) 1125 1126 >>> parse("01h02s", default=DEFAULT) 1127 datetime.datetime(2003, 9, 25, 1, 0, 2) 1128 1129 1130With AM/PM: 1131 1132.. doctest:: tz 1133 1134 >>> parse("10h am", default=DEFAULT) 1135 datetime.datetime(2003, 9, 25, 10, 0) 1136 1137 >>> parse("10pm", default=DEFAULT) 1138 datetime.datetime(2003, 9, 25, 22, 0) 1139 1140 >>> parse("12:00am", default=DEFAULT) 1141 datetime.datetime(2003, 9, 25, 0, 0) 1142 1143 >>> parse("12pm", default=DEFAULT) 1144 datetime.datetime(2003, 9, 25, 12, 0) 1145 1146 1147Some special treating for ''pertain'' relations: 1148 1149.. doctest:: tz 1150 1151 >>> parse("Sep 03", default=DEFAULT) 1152 datetime.datetime(2003, 9, 3, 0, 0) 1153 1154 >>> parse("Sep of 03", default=DEFAULT) 1155 datetime.datetime(2003, 9, 25, 0, 0) 1156 1157 1158Fuzzy parsing: 1159 1160.. doctest:: tz 1161 :options: +NORMALIZE_WHITESPACE 1162 1163 >>> s = "Today is 25 of September of 2003, exactly " \ 1164 ... "at 10:49:41 with timezone -03:00." 1165 >>> parse(s, fuzzy=True) 1166 datetime.datetime(2003, 9, 25, 10, 49, 41, 1167 tzinfo=tzoffset(None, -10800)) 1168 1169 1170Other random formats: 1171 1172.. doctest:: tz 1173 1174 >>> parse("Wed, July 10, '96") 1175 datetime.datetime(1996, 7, 10, 0, 0) 1176 1177 >>> parse("1996.07.10 AD at 15:08:56 PDT", ignoretz=True) 1178 datetime.datetime(1996, 7, 10, 15, 8, 56) 1179 1180 >>> parse("Tuesday, April 12, 1952 AD 3:30:42pm PST", ignoretz=True) 1181 datetime.datetime(1952, 4, 12, 15, 30, 42) 1182 1183 >>> parse("November 5, 1994, 8:15:30 am EST", ignoretz=True) 1184 datetime.datetime(1994, 11, 5, 8, 15, 30) 1185 1186 >>> parse("3rd of May 2001") 1187 datetime.datetime(2001, 5, 3, 0, 0) 1188 1189 >>> parse("5:50 A.M. on June 13, 1990") 1190 datetime.datetime(1990, 6, 13, 5, 50) 1191 1192 1193Override parserinfo with a custom parserinfo 1194 1195.. doctest:: tz 1196 1197 >>> from dateutil.parser import parse, parserinfo 1198 >>> class CustomParserInfo(parserinfo): 1199 ... # e.g. edit a property of parserinfo to allow a custom 12 hour format 1200 ... AMPM = [("am", "a", "xm"), ("pm", "p")] 1201 >>> parse('2018-06-08 12:06:58 XM', parserinfo=CustomParserInfo()) 1202 datetime.datetime(2018, 6, 8, 0, 6, 58) 1203 1204 1205 1206tzutc examples 1207-------------- 1208 1209.. doctest:: tzutc 1210 1211 >>> from datetime import * 1212 >>> from dateutil.tz import * 1213 1214 >>> datetime.now() 1215 datetime.datetime(2003, 9, 27, 9, 40, 1, 521290) 1216 1217 >>> datetime.now(tzutc()) 1218 datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc()) 1219 1220 >>> datetime.now(tzutc()).tzname() 1221 'UTC' 1222 1223 1224tzoffset examples 1225----------------- 1226 1227.. doctest:: tzoffset 1228 :options: +NORMALIZE_WHITESPACE 1229 1230 >>> from datetime import * 1231 >>> from dateutil.tz import * 1232 1233 >>> datetime.now(tzoffset("BRST", -10800)) 1234 datetime.datetime(2003, 9, 27, 9, 52, 43, 624904, 1235 tzinfo=tzinfo=tzoffset('BRST', -10800)) 1236 1237 >>> datetime.now(tzoffset("BRST", -10800)).tzname() 1238 'BRST' 1239 1240 >>> datetime.now(tzoffset("BRST", -10800)).astimezone(tzutc()) 1241 datetime.datetime(2003, 9, 27, 12, 53, 11, 446419, 1242 tzinfo=tzutc()) 1243 1244 1245tzlocal examples 1246---------------- 1247 1248.. doctest:: tzlocal 1249 1250 >>> from datetime import * 1251 >>> from dateutil.tz import * 1252 1253 >>> datetime.now(tzlocal()) 1254 datetime.datetime(2003, 9, 27, 10, 1, 43, 673605, 1255 tzinfo=tzlocal()) 1256 1257 >>> datetime.now(tzlocal()).tzname() 1258 'BRST' 1259 1260 >>> datetime.now(tzlocal()).astimezone(tzoffset(None, 0)) 1261 datetime.datetime(2003, 9, 27, 13, 3, 0, 11493, 1262 tzinfo=tzoffset(None, 0)) 1263 1264 1265tzstr examples 1266-------------- 1267Here are examples of the recognized formats: 1268 1269 * `EST5EDT` 1270 * `EST5EDT4,M4.1.0/02:00:00,M10-5-0/02:00` 1271 * `EST5EDT4,95/02:00:00,298/02:00` 1272 * `EST5EDT4,J96/02:00:00,J299/02:00` 1273 1274Notice that if daylight information is not present, but a 1275daylight abbreviation was provided, `tzstr` will follow the 1276convention of using the first sunday of April to start daylight 1277saving, and the last sunday of October to end it. If start or 1278end time is not present, 2AM will be used, and if the daylight 1279offset is not present, the standard offset plus one hour will 1280be used. This convention is the same as used in the GNU libc. 1281 1282This also means that some of the above examples are exactly 1283equivalent, and all of these examples are equivalent 1284in the year of 2003. 1285 1286Here is the example mentioned in the 1287 1288[https://docs.python.org/3/library/time.html time module documentation]. 1289 1290.. testsetup:: tzstr 1291 1292 import os 1293 import time 1294 from datetime import datetime 1295 from dateutil.tz import tzstr 1296 1297.. doctest:: tzstr 1298 1299 >>> os.environ['TZ'] = 'EST+05EDT,M4.1.0,M10.5.0' 1300 >>> time.tzset() 1301 >>> time.strftime('%X %x %Z') 1302 '02:07:36 05/08/03 EDT' 1303 >>> os.environ['TZ'] = 'AEST-10AEDT-11,M10.5.0,M3.5.0' 1304 >>> time.tzset() 1305 >>> time.strftime('%X %x %Z') 1306 '16:08:12 05/08/03 AEST' 1307 1308 1309And here is an example showing the same information using `tzstr`, 1310without touching system settings. 1311 1312.. doctest:: tzstr 1313 1314 >>> tz1 = tzstr('EST+05EDT,M4.1.0,M10.5.0') 1315 >>> tz2 = tzstr('AEST-10AEDT-11,M10.5.0,M3.5.0') 1316 >>> dt = datetime(2003, 5, 8, 2, 7, 36, tzinfo=tz1) 1317 >>> dt.strftime('%X %x %Z') 1318 '02:07:36 05/08/03 EDT' 1319 >>> dt.astimezone(tz2).strftime('%X %x %Z') 1320 '16:07:36 05/08/03 AEST' 1321 1322 1323Are these really equivalent? 1324 1325.. doctest:: tzstr 1326 1327 >>> tzstr('EST5EDT') == tzstr('EST5EDT,M4.1.0,M10.5.0') 1328 True 1329 1330 1331Check the daylight limit. 1332 1333.. doctest:: tzstr 1334 1335 >>> tz = tzstr('EST+05EDT,M4.1.0,M10.5.0') 1336 >>> datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname() 1337 'EST' 1338 >>> datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname() 1339 'EDT' 1340 >>> datetime(2003, 10, 26, 0, 59, tzinfo=tz).tzname() 1341 'EDT' 1342 >>> datetime(2003, 10, 26, 2, 00, tzinfo=tz).tzname() 1343 'EST' 1344 1345 1346tzrange examples 1347---------------- 1348 1349.. testsetup:: tzrange 1350 1351 from dateutil.tz import tzrange, tzstr 1352 1353.. doctest:: tzrange 1354 1355 >>> tzstr('EST5EDT') == tzrange("EST", -18000, "EDT") 1356 True 1357 1358 >>> from dateutil.relativedelta import * 1359 >>> range1 = tzrange("EST", -18000, "EDT") 1360 >>> range2 = tzrange("EST", -18000, "EDT", -14400, 1361 ... relativedelta(hours=+2, month=4, day=1, 1362 ... weekday=SU(+1)), 1363 ... relativedelta(hours=+1, month=10, day=31, 1364 ... weekday=SU(-1))) 1365 >>> tzstr('EST5EDT') == range1 == range2 1366 True 1367 1368 1369Notice a minor detail in the last example: while the DST should end 1370at 2AM, the delta will catch 1AM. That's because the daylight saving 1371time should end at 2AM standard time (the difference between STD and 1372DST is 1h in the given example) instead of the DST time. That's how 1373the `tzinfo` subtypes should deal with the extra hour that happens 1374when going back to the standard time. Check 1375 1376[https://docs.python.org/3/library/datetime.html#datetime.tzinfo tzinfo documentation] 1377 1378for more information. 1379 1380tzfile examples 1381--------------- 1382 1383.. testsetup:: tzfile 1384 1385 from datetime import datetime 1386 from dateutil.tz import tzfile, tzutc 1387 1388.. doctest:: tzfile 1389 :options: +NORMALIZE_WHITESPACE 1390 1391 >>> tz = tzfile("/etc/localtime") 1392 >>> datetime.now(tz) 1393 datetime.datetime(2003, 9, 27, 12, 3, 48, 392138, 1394 tzinfo=tzfile('/etc/localtime')) 1395 1396 >>> datetime.now(tz).astimezone(tzutc()) 1397 datetime.datetime(2003, 9, 27, 15, 3, 53, 70863, 1398 tzinfo=tzutc()) 1399 1400 >>> datetime.now(tz).tzname() 1401 'BRST' 1402 >>> datetime(2003, 1, 1, tzinfo=tz).tzname() 1403 'BRDT' 1404 1405 1406Check the daylight limit. 1407 1408.. doctest:: tzfile 1409 1410 >>> tz = tzfile('/usr/share/zoneinfo/EST5EDT') 1411 >>> datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname() 1412 'EST' 1413 >>> datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname() 1414 'EDT' 1415 >>> datetime(2003, 10, 26, 0, 59, tzinfo=tz).tzname() 1416 'EDT' 1417 >>> datetime(2003, 10, 26, 1, 00, tzinfo=tz).tzname() 1418 'EST' 1419 1420 1421tzical examples 1422--------------- 1423Here is a sample file extracted from the RFC. This file defines 1424the `EST5EDT` timezone, and will be used in the following example. 1425 1426.. include:: samples/EST5EDT.ics 1427 :literal: 1428 1429And here is an example exploring a `tzical` type: 1430 1431.. doctest:: tzfile 1432 1433 >>> from dateutil.tz import *; from datetime import * 1434 1435 >>> tz = tzical('samples/EST5EDT.ics') 1436 >>> tz.keys() 1437 ['US-Eastern'] 1438 1439 >>> est = tz.get('US-Eastern') 1440 >>> est 1441 <tzicalvtz 'US-Eastern'> 1442 1443 >>> datetime.now(est) 1444 datetime.datetime(2003, 10, 6, 19, 44, 18, 667987, 1445 tzinfo=<tzicalvtz 'US-Eastern'>) 1446 1447 >>> est == tz.get() 1448 True 1449 1450 1451Let's check the daylight ranges, as usual: 1452 1453.. doctest:: tzfile 1454 1455 >>> datetime(2003, 4, 6, 1, 59, tzinfo=est).tzname() 1456 'EST' 1457 >>> datetime(2003, 4, 6, 2, 00, tzinfo=est).tzname() 1458 'EDT' 1459 1460 >>> datetime(2003, 10, 26, 0, 59, tzinfo=est).tzname() 1461 'EDT' 1462 >>> datetime(2003, 10, 26, 1, 00, tzinfo=est).tzname() 1463 'EST' 1464 1465 1466tzwin examples 1467-------------- 1468 1469.. doctest:: tzwin 1470 1471 >>> tz = tzwin("E. South America Standard Time") 1472 1473 1474tzwinlocal examples 1475------------------- 1476 1477 1478.. doctest:: tzwinlocal 1479 1480 >>> tz = tzwinlocal() 1481 1482# vim:ts=4:sw=4:et 1483