Package: datestuff
For when you need somedatetimehelpers but not a complete replacement for the modules.Why?Frankly, I love the built indatetimemodule. Almost everything I need to do, I can just do with it.However, a few things tend to creep up datetime and datetime again. Things like:Creating a range of datesCreating an unfixed dateChecking if two datetimes are within a certain delta of one anotherHere’s a short look at what’s included.RelativeDate and RelativeDateTimeThese allow you to create an unfixeddateordatetimeinstance by providing atimedeltaoffset and/or factory method.By default,RelativeDateusesdate.todayandRelativeDateTimeusesdatetime.nowas the default factories and both have a default offset oftimedelta(0):rd=RelativeDate()rd.as_date()# date(2016, 7, 24)rdt=RelativeDateTime()rd.as_datetime()# datetime(2016, 7, 24, 12, 29)However, it is also possible to provide other factories as well:importarrowrdt=RelativeDateTime(clock=arrow.utcnow)rdt.as_datetime()# <Arrow [2016-07-24T17:34:58.970460+00:00]>And as long as the underlying factory produces adateordatetimecompatible object, everything willjust work. By compatible, I mean implements thedateordatetimeinterface.Additionally, if only a static offset from today or now is desired, you can simply provide the offset argument with atimedeltaor dateutilrelativedelta. Note that currently,timedeltaandrelativedeltaare not interoperable.fromdatetimeimporttimedeltard=RelativeDate(offset=timedelta(days=6))rd.as_date()# date(2016, 7, 30)RelativeDateandRelativeDateTimealso allow comparing against regulardateanddatetimeinstances with the standard operators (==, !=, >, etc). Making these incredibly useful for quickly defining date boundaries that are defined statically (such as in a serializer or ORM model):fromdatetimeimporttimedelta,daterd=RelativeDate(offset=timedelta(days=7))assertrd>date.today()# always trueAdding and subtracting relative instances actually operate on their offsets, rather than underlyingdateordatetimevalues.fromdatetimeimporttimedeltard=RelativeDate(offset=timedelta(days=1))rd+rd==RelativeDate(offset(timedelta(days=2)))rd-rd==RelativeDate()Some alternate constructors are provided where it makes sense, each allows passing an offset but defaults totimedelta(), provided are:RelativeDate.today: the default constructorRelativeDateTime.now: the default constructor, allows passing a tzinfo object to the factoryRelativeDateTime.utcnow: factory produces UTC-based datetimes (note: these are NAIVE as it relies on the underlyingdatetime.utcnow)RelativeDateTime.today: the default constructor, does not allow passing a tzinfo objectFor convenience sake there are also truly static constructors:RelativeDate.fromdate: hoists a regular date into relative contextRelativeDateTime.fromdatetime: hoists a regular datetime intoRelativeDateTime.fromdate: hoists a date into aRelativeDateTimecontext, allows passing a tzinfo object, factory looks likedatetime.combine(the_date, time(tzinfo=tzinfo))Any additional static constructors, such asdatetime.strptime, can be derived from these if truly needed.fromdatetimeimportdate,time,timedeltard=RelativeDate.fromdate(date(2016,7,24),offset=timedelta(days=7))rd.as_date()# date(2016, 7, 31), alwaysFinally, any functionality not implemented directly in the relative instance is proxied to the underlyingdateordatetimeinstance.DateRangeA range of dates is another tool I find myself needing from time to time, however eager creation can sometimes be very expensive for a large range.Instead,DateRangeis modeled after the Python 3rangetype, which has fast path lookup for membership, lazy iteration, indexing and slicing (slices return newDateRangeobjects)fromdatestuffimportDateRangefromdatetimeimportdate,timedeltadr=DateRange(start=date(2016,1,1),stop=date(2016,12,31),step=timedelta(days=7))date(2016,1,8)indr# truelen(dr)# 53, yes this is correctlist(dr)# [date(2016, 1, 1), date(2016, 1, 8), ...]dr[1]==date(2016,1,8)# Truedr[1:-1:2]==DateRange(date(2016,1,8),date(2016,12,30),step=timedelta(days=14))# TrueDateRangealso allows creating an open ended range by simply omitting the stop argument. In this case, the only functionality that will not work is usinglenand negative indexing/slicing (as there is no end)Currently,DateRangedoes not supportrelativedeltaas under the hood it usestimedelta.total_secondsfor Python 2 and 3 compatiblity. This could be resolved in the future, but is unlikely.DateRangeis, however, compatible withdateanddatetimelike objects and othertimedeltalike objects. Interestingly, this would apply toRelativeDateandRelativeDateTimeas well.utilsCurrently, the only util iswithin_deltawhich is useful for comparing twodateordatetime(or like) instances within a certain delta.fromdatetimeimportdatetime,timedeltafromdatestuffimportwithin_deltad1=datetime.now()d2=datetime.now()d1==d2# falsewithin_delta(d1,d2,timedelta(seconds=1))# trueIf simple boundary checking is needed, this tool is much more light weight than eitherDateRangeorRelativeDate. Sadly, this is another tool that cannot interoperate withrelativedeltaas it andtimedeltaare unorderable (at least in Python 3).The MIT License (MIT)
Copyright (c) 2016 Alec Nikolas ReiterPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.