From lemburg@uni-duesseldorf.de Mon Dec 1 10:04:20 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Mon, 01 Dec 1997 11:04:20 +0100 Subject: Don't DROP for fun, was:Re: [DB-SIG] ANN: mxODBC Version 0.3 References: <4D0A23B3F74DD111ACCD00805F31D8104536E3@red-msg-50.dns.microsoft.com> <3.0.1.32.19971130224618.007c0100@mail1.tripnet.se> Message-ID: <34828BA4.533DBD28@uni-duesseldorf.de> Magnus Lycka wrote: > > At 12:51 1997-11-29 +0100, M.-A. Lemburg wrote: > >The DB API gave me the impression that you'll always have to > >explicitly call .commit() to get your changes committed. Now what > >if someone else also gets this impression and then drops some > >tables just for the fun it... I'm sure he'd get into a lot of > >trouble, if the module would have autocommitted his requests. > > Ouch! He would anyway! > > SQL is divided into two parts: The data definition languages (DDL) > and the data manipulation language (DML) *). The DDL consists of > statements that define the database structure such as CREATE and DROP. > The DML consists of the statements used in changing and querying > database content such as INSERT, UPDATE, DELETE and SELECT. > > COMMIT and ROLLBACK (and sometimes SAVEPOINT) are used to make > multiple DML statements into a single transaction. They do NOT > regulate DDL statements. Your DROP TABLE happens at once! At least > with the databases I've worked with. (I just tested with Oracle.) Ooops, don't know if it's specific to my DB, but db.rollback() get's me the dropped tables back. Shouldn't be mentioning that drastic example if ROLLBACK doesn't apply in general though, sorry. > > Magnus > > ---- > *) Some people would even say that queries aren't manipulation (and > I guess that is true) and say that data query language (DQL) is > something separate. I.e. SELECT would be DQL, not DML. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From gstein@exchange.microsoft.com Mon Dec 1 15:50:25 1997 From: gstein@exchange.microsoft.com (Greg Stein (Exchange)) Date: Mon, 1 Dec 1997 07:50:25 -0800 Subject: [DB-SIG] ANN: mxODBC Version 0.3 Message-ID: <69D8143E230DD111B1D40000F8485840BCB57C@ED> [forgive my stupid mail editor here...] Jim Fulton writes: > Bill Tutt writes: > > Specfically: noError, opError, progError, integrityError, > > dataError, and internalError > > > > Where they apply to the following cases: > This should be part of the DBI spec. It currently isn't. > > Autocommit: You default to off, when ODBC defaults to on. > These semantics are not documented in the DBI spec, but should be. > All database interfaces should provide the same semantics wrt > autocommit. > ... > > Ditching DBI: > > That was a particulary silly thing to do, the exceptions listed > > above exist > But are not documented. I never got the time to update the spec and gave up. I suggested closing down the db-sig, but people pointed out that it still had more work to do. Namely, completing an update of the spec. So far, that task hasn't even appeared on the db-sig, let alone anybody stepping up to do it or contributing to an update in any way. So... the best thing people can do to reduce confusion is stop working on code and spend some time on that spec. Another thing might be to break dbi out of the various distributions into its own module available from python.org. -g _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Tue Dec 2 20:12:51 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Tue, 02 Dec 1997 21:12:51 +0100 Subject: [DB-SIG] ANN: mxODBC Version 0.5 References: <69D8143E230DD111B1D40000F8485840BCB57C@ED> Message-ID: <34846BC2.4E5B192@uni-duesseldorf.de> Greg Stein (Exchange) wrote: > I never got the time to update the spec and gave up. I suggested closing > down the db-sig, but people pointed out that it still had more work to > do. Namely, completing an update of the spec. So far, that task hasn't > even appeared on the db-sig, let alone anybody stepping up to do it or > contributing to an update in any way. Ok, I'll give it a try. Are the exceptions Bill posted the only things that were added since version 1.0 ? > So... the best thing people can do to reduce confusion is stop working > on code ... now that is a strange proposal :-) > and spend some time on that spec. Another thing might be to > break dbi out of the various distributions into its own module available > from python.org. But then you would take away the freedom of programmers wanting to code their dbi-module in Python. With the new standard package mechanism the naming confusion about the dbi module is reduced to a minimum anyway. It just needs to be made clear that every DB module needs to provide one. BTW: I have added the alternative date/time format I proposed earlier to mxODBC. To use it, you have to set a cursor variable called 'datetimeformat' to (currently) either TIMEVALUE_DATETIMEFORMAT (t_time-based values) or TUPLE_DATETIMEFORMAT (tuple-based values). The tuples use these mappings: time (hour,min,sec) date (year,month,day) timestamp (year,month,day,hour,minute,second,microsecond) Are these names/mappings ok with you ? -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Wed Dec 3 11:34:14 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Wed, 03 Dec 1997 12:34:14 +0100 Subject: [DB-SIG] DB-API Spec. 1.1a1 Message-ID: <348543B6.9A72B97@uni-duesseldorf.de> Please have a look: http://starship.skyport.net/~lemburg/DatabaseAPI-1.1.html I've so far added the exceptions (under new names though) that the odbc module introduced and clearified a few other things. Most significant change: - dbi-type objects must now only be "equal" to the values returned in cursor.description. This is to allow more than one value returned there to be matched by one of the dbi-objects. Points to discuss (apart from the above): - Do we really need display_size and internal_size in the description ? Python has it's own formatting, so these values aren't really that interesting. - The date/time format. I'd opt for making different alternatives available which can be chosen on a per execute basis, e.g. you can set the format prior to each execute(), but the format then applies to all parameters. There should be new functions in dbi for interfacing to these formats and a way to set the default format (per connection). -- Marc-Andre Lemburg PS to Christian: the reverse lookup on starship still doesn't work yet. _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From hannu@trust.ee Wed Dec 3 15:15:31 1997 From: hannu@trust.ee (Hannu Krosing) Date: Wed, 03 Dec 1997 17:15:31 +0200 Subject: [DB-SIG] DB-API Spec. 1.1a1 References: <348543B6.9A72B97@uni-duesseldorf.de> Message-ID: <34857793.5C072B43@sid.trust.ee> M.-A. Lemburg wrote: > Please have a look: > > http://starship.skyport.net/~lemburg/DatabaseAPI-1.1.html > > I've so far added the exceptions (under new names though) that > the odbc module introduced and clearified a few other things. Good to see somebody working on it again > Most significant change: > - dbi-type objects must now only be "equal" to the values returned > in cursor.description. This is to allow more than one value returned > there to be matched by one of the dbi-objects. can't we still have _one_ dbi module, that the db modules also use so that we can still do the 'is' comparison.this is needed for exceptions anyhow. Also, considering the new packaging scheme in 1.5, the db interface might also be restructured to use the new scheme. so that it will actually be db.interface or something > Points to discuss (apart from the above): > - Do we really need display_size and internal_size in the description ? > Python has it's own formatting, so these values aren't really that > interesting. We will need something like max_size (for varchars for example), this would probably be equal to the display_size. The internal size is probably useless, except for passing to some other modules I can't imagine right now ;) > - The date/time format. I'd opt for making different alternatives > available which can be chosen on a per execute basis, e.g. you > can set the format prior to each execute(), but the format then > applies to all parameters. There should be new functions in dbi > for interfacing to these formats and a way to set the default > format (per connection). I think that the dbiDate should be defined for tuple or three args as well (that's the format that I use most of the time) and dbiTime and dbiDateTime also added. also, for example Postgres has several additional datatypes (geometric, array, ...), so should we also add descriptors for them into the dbi module. or could we use an approach like os.path does, meaning that each db module has a member called dbi, that may or may not be the universal dbi module (on linux os.path is in fact module 'posixpath'). In case the db.dbi is not same as global dbi, it should at least import the global one and reexpose the imported type and exception objects. Hannu Krosing _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Fri Dec 5 11:32:52 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Fri, 05 Dec 1997 12:32:52 +0100 Subject: [DB-SIG] DB-API Spec. 1.1a1 References: <348543B6.9A72B97@uni-duesseldorf.de> <34857793.5C072B43@sid.trust.ee> <3485A359.756B84@uni-duesseldorf.de> <3487E62F.6559F45@uni-duesseldorf.de> Message-ID: <3487E664.4F3A5E7A@uni-duesseldorf.de> Funny, now that I've started to put some discussion points regarding a new API Spec on the list nobody except Hannu seems interested anymore -- or is it just lack of time ? I'm still looking for "the best way" to set date/time formats. Hannu put up the very interesting idea of having execute() decide itself for input parameters. This can easily be done, since all the module has to test is whether it got a tuple or a number (float) and the addition is fully backward compatible. But what about the output from the fetch-methods ? I considered using a cursor variable for this, but other ways are also thinkable: - add a parameter to the fetch-methods setting the wanted date/time format - add a parameter to execute for setting the format for all later calls to fetch-methods Do we need more formats apart from tuples and time floats for date/time values, maybe strings ? -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From billtut@microsoft.com Fri Dec 5 21:45:43 1997 From: billtut@microsoft.com (Bill Tutt) Date: Fri, 5 Dec 1997 13:45:43 -0800 Subject: [DB-SIG] DB-API Spec. 1.1a1 Message-ID: <4D0A23B3F74DD111ACCD00805F31D810453703@red-msg-50.dns.microsoft.com> Its severe lack of time I'm afraid.. If I had the time, I'd have made all the necessary updates to the Win32 ODBC codebase... If only I was getting paid to do Python database work.. *sigh* Instead I'm busy using ATL OLE DB Consumer templates in C++... The "best way" for date/time formats is easy.. DON'T The reason you don't want to do this is because it imposes an uncessary requirement on the code that works with the database i.e. dealing with different date formats.. Thats just silly. The specifics for any date/time format is quite easy... 1) Data its storing i.e. (year, month, day, hour, minute, second, billionths of a second as an integer) 2) A method to format the date (perferabbly using a strftime() format string, with an extension for parts of the data type that strftime() doesn't deal with) 3) A method to parse a date given a strftime() like format string. #'s 2 & 3 should be preferrably written in C Additional code that will need to be written will be some code to convert a C double into this date type, as well as conver this date type into a double. The OLE DateTime type uses a double to represent dates. All the execute() method should care about is the fact that it is a date, and the best way for it to tell if its a date, is to have a C based date module, and make all your dates as instances of types in said module. So that it can just do a type check instead of doing "tuple recognition".. The reason for having the above in a C module is two fold.. 1) Shorten the work the C code has to do to accomplish the input binding to the database. 2) So the C code can easily create and make use of the date type. Again, DO NOT allow a format for transferring dates in strings in your Python program... Parse a date you get into a date type, and pass that to execute(). Bill Tutt billtut@microsoft.com Not speaking for Microsoft, etc... > -----Original Message----- > From: M.-A. Lemburg [SMTP:lemburg@uni-duesseldorf.de] > Sent: Friday, December 05, 1997 3:33 AM > To: DB-SIG @ Python.org > Subject: Re: [DB-SIG] DB-API Spec. 1.1a1 > > Funny, now that I've started to put some discussion points > regarding a new API Spec on the list nobody except Hannu > seems interested anymore -- or is it just lack of time ? > > I'm still looking for "the best way" to set date/time formats. > Hannu put up the very interesting idea of having execute() > decide itself for input parameters. This can easily be > done, since all the module has to test is whether it got a > tuple or a number (float) and the addition is fully backward compatible. > But what about the output from the fetch-methods ? I considered > using a cursor variable for this, but other ways are also > thinkable: > - add a parameter to the fetch-methods setting the wanted > date/time format > - add a parameter to execute for setting the format for all > later calls to fetch-methods > > Do we need more formats apart from tuples and time floats > for date/time values, maybe strings ? > > -- > Marc-Andre Lemburg > > > _______________ > DB-SIG - SIG on Tabular Databases in Python > > send messages to: db-sig@python.org > administrivia to: db-sig-request@python.org > _______________ _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From magnus.lycka@tripnet.se Fri Dec 5 13:46:43 1997 From: magnus.lycka@tripnet.se (Magnus Lycka) Date: Fri, 05 Dec 1997 14:46:43 +0100 Subject: [DB-SIG] DB-API Spec. 1.1a1 In-Reply-To: <3487E664.4F3A5E7A@uni-duesseldorf.de> References: <348543B6.9A72B97@uni-duesseldorf.de> <34857793.5C072B43@sid.trust.ee> <3485A359.756B84@uni-duesseldorf.de> <3487E62F.6559F45@uni-duesseldorf.de> Message-ID: <3.0.1.32.19971205144643.007ea100@mail1.tripnet.se> At 12:32 1997-12-05 +0100, M.-A. Lemburg wrote: >Do we need more formats apart from tuples and time floats >for date/time values, maybe strings ? No. I have to admit that I haven't actually used the DBI yet, although I plan to do so soon. I assume that the tuple is the ordinary python time module tuple. I guess that's the standard way to treat dates in Python. Sure, we often want dates as strings, but a) often these dates (that should all have the same format) comes from somewhere else than the database, and b) the formats vary wildly depending on locale, taste etc. Therefore, I suggest that string formatting of date is left outside the DBI. For standard C look, there is time.asctime(), and for other formats, we write our own dateformat.py modules or watever. Actuslly, I've been planning to write some kind of 'domains.py' module where I define classes for dates, timestamps, money etc with relevant attributes and methods. Is there anyone who has done so, or would be interested in commenting? Magnus -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Sat Dec 6 11:56:43 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Sat, 06 Dec 1997 12:56:43 +0100 Subject: [DB-SIG] DB-API Spec. 1.1a1 References: <348543B6.9A72B97@uni-duesseldorf.de> <34857793.5C072B43@sid.trust.ee> <3485A359.756B84@uni-duesseldorf.de> <3487E62F.6559F45@uni-duesseldorf.de> <3.0.1.32.19971205144643.007ea100@mail1.tripnet.se> Message-ID: <34893D7B.21872233@uni-duesseldorf.de> Magnus Lycka wrote: > > At 12:32 1997-12-05 +0100, M.-A. Lemburg wrote: > >Do we need more formats apart from tuples and time floats > >for date/time values, maybe strings ? > > No. I must admit, my question was more of a rhetorical nature :-) > Actuslly, I've been planning to write some kind of 'domains.py' > module where I define classes for dates, timestamps, money etc > with relevant attributes and methods. Is there anyone who has > done so, or would be interested in commenting? You should contact Martin v. Loewis on this: he wrote the locale module that is in the standard distribution now. It currently only includes functions to do number formatting. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Sat Dec 6 11:49:52 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Sat, 06 Dec 1997 12:49:52 +0100 Subject: [DB-SIG] DB-API Spec. 1.1a1 References: <4D0A23B3F74DD111ACCD00805F31D810453703@red-msg-50.dns.microsoft.com> Message-ID: <34893BE0.2AB091A3@uni-duesseldorf.de> Bill Tutt wrote: > > The "best way" for date/time formats is easy.. DON'T > The reason you don't want to do this is because it imposes an uncessary > requirement on the code that works with the database i.e. dealing with > different date formats.. Thats just silly. > > The specifics for any date/time format is quite easy... > > 1) Data its storing i.e. (year, month, day, hour, minute, second, billionths > of a second as an integer) > 2) A method to format the date > (perferabbly using a strftime() format string, with an extension for > parts of the data type that strftime() doesn't > deal with) > 3) A method to parse a date given a strftime() like format string. > #'s 2 & 3 should be preferrably written in C Is this possible ? Take months for example: these can are formatted in the current locale's writing by strftime(), so we would have to adapt these too somehow. But to start we could skip these formats for the time being. I'm currently using a function which knows about these formats: - 1.1.90, 01.01.90, 1.1.1990 (date only, time defaults to 0:00:00) - 1.1. (current year is appended, 0:00:00) - 1.1.90 14:00 - 14:00 (today is used as date) I've never run into a situation where I want to parse input of the form 'Friday, Oct. 13'. This is just much to error prone (real users even have problems with the above...). > Additional code that will need to be written will be some code to convert a > C double into this date type, > as well as conver this date type into a double. > The OLE DateTime type uses a double to represent dates. All this sounds like there is a need for a new DateTime-type in general -- which is a good idea (has anyone ever tried to handle historic dates in Python?). But that type should then become part of the Python distribution and thus needs to be well cooked. There was some discussion about date/time parsing a few months ago -- don't know if it has produced any downloadable effects though. Maybe we should have a look into that too. > All the execute() method should care about is the fact that it is a date, > and the best way for it to tell if its a date, is to have a C based date > module, and make all your dates as instances > of types in said module. So that it can just do a type check instead of > doing "tuple recognition".. You've got a point there. But again: this module should be a generic one with a suitable C API for DB modules to use. Say, the OLE double format... is that the one where the date is encoded in the whole part and the time in the fraction part ? Christian told me about such a format. > > The reason for having the above in a C module is two fold.. > 1) Shorten the work the C code has to do to accomplish the input binding to > the database. > 2) So the C code can easily create and make use of the date type. > > Again, DO NOT allow a format for transferring dates in strings in your > Python program... > Parse a date you get into a date type, and pass that to execute(). Ok. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Sat Dec 6 13:00:48 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Sat, 06 Dec 1997 14:00:48 +0100 Subject: [DB-SIG] DB-API Spec. 1.1a1 References: <4D0A23B3F74DD111ACCD00805F31D810453703@red-msg-50.dns.microsoft.com> <34893BE0.2AB091A3@uni-duesseldorf.de> Message-ID: <34894C80.769B3C20@uni-duesseldorf.de> M.-A. Lemburg wrote: > > There was some discussion about date/time parsing a few months > ago -- don't know if it has produced any downloadable effects though. > Maybe we should have a look into that too. Some searching did bring up some code in that direction. I found a date-parsing module that Skip Montanaro has written and a post by Jim Fulton asking for specifics af such a module. He also wrote something about "making it available to a general public". Jim, have you written anything in that direction -- haven't found it on www.digicool.com. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From mU1LceXy4@offsh1or.com Fri Dec 5 05:17:22 1997 From: mU1LceXy4@offsh1or.com (mU1LceXy4@offsh1or.com) Date: 05 Dec 97 5:17:22 PM Subject: [DB-SIG] Lasers/Optics/Optical Tables - Save! Message-ID: MWK INDUSTRIES SALE! JUST A QUICK LETTER TO SHOW YOU SOME LASERS- OPTICS AND OPTICAL TABLES SURPLUS THAT WE JUST RECEIVED. ITEM TRIMMU12 14 WATT ARGON LASER MADE FOR HEART SURGERY, TRIMEDYNE MODEL 900 TEMOO, POLORIZED,220VAC INPUT , WATER COOLED , FIBER LAUNCH, ALL ON ROLLAROUND CART EXCELENT FOR LAB USE, THE POWER WAS MEASURED AT 13 TO 14 WATTS. PRICE $9500 12 MONTH WARRANTEE. ITEM: COHERENT ARTICULATING ARM FROM A MODEL 451 CO2 MEDICAL LASER. ECCELLENT COND. $200 ITEM CO220A: CO2 LASER MADE BY PFIZER ,1990, FOR SURGERY, TATTOO REMOVAL ECT. 20 WATT OUTPUT , TESTED AND IN EXC. COND. 110 VAC INPUT, COST $40,000 NEW OUR PRICE 4,900. MODEL 20-C ITEM:PDA-1U1 SPECTRA PHYSICS QUANTRA RAY PULSED DYE LASER , GOOD FOR SPARE PARTS MODEL PDA-1 $500 ITEM NEWU1 NEWPORT OPTICAL TABLE 16" BY 36" 4" THICK, 1 " HOLE SPACING, COMES WITH A RUBBER ISOLATED TABLE STAND, NOT AIR SUPPORTED, $750 ITEM: HEPSN1 HELIUM NEON POWER SUPPLY KIT OPERATES UP TO A 15 mW LASER, INCLUDES ALL COMPONENTS AND PRINTED CIRCUIT BOARD, ALL YOU HAVE TO DO IS STUFF AND SOLDER THE CIRCUIT BOARD . 4" BY 3" BY 3", PRICE $75 ITEM HENEU12 1 TO 1.5 MW HE-NE LASER 632.8 nM INCLUDES 12VDC INPUT POWER SUPPLY ALL IN A PLASTIC HOUSING 6.25 IN. BY 1.375IN BY 2.25 IN. TEMOO,RANDOM POL. ,1.7 MR DIVERGENCE. 12 MONTH WARRANTEE , PRICE $45 ITEM MELU12 1 TO 2 mW HE-NE LASER 632.8 NM , PULLS FROM MEDICAL EQUIPMENT .EACH UNIT INCLUDES HE-NE HEAD AND POWER SUPPLY[110VAC INPUT]. ALL YOU NEED TO PROVIDE IS A POWER CORD AND A FUSE TO MAKE THE UNIT OPERATIONAL. THE BEAM IS TEM00, POLORIZED WE WILL COVER EACH UNIT WITH A 12 MONTH UNLIMITED HOUR WARRANTEE, EXCELLENT FOR FOR LAB OR HOME USE. NEW THESE COST APPROX. $350 OUR PRICE $85. DIMENSIONS 9.75 BY 1.25 INCHES, P.S. 4.25 BY 3.25BY 1.25 INCHES. ITEM RAMCNS1: RAMAN CELL OPTICS 308 nm AR/AR 4600 A 0=0 DEGREES 1000 MM FL. 2" DIA. NEW. ORIGINAL PRICE $520 OUR PRICE $175 ITEM TFPOLNS1: POLARIZERS , THIN FILM FOR 532 nm , NEW, ORIGINAL COST $590 EACH OUR PRICE $200 EACH 10 MM DIA. ITEM CO2OCNS1: CO2 HIGH REFECTOR AND OUTPUT COUPLER 10.5 MM DIA, OC =79%R NEW. $200 A SET. ITEM 25MNS1: DIELECTRIC BROADBAND MIRRORS 450 TO 700NM , NEW WITH PLASTIC PROTECTIVE COATINGS , 2 SIZES 25 MM SQ. AND 50 MM SQ. RECOMENDED FOR HIGHER POWER LASERS. 25MM SIZE ITEM 25MNS1 $20 50MM SIZE ITEM 50MNS1 $25 ITEM # BSDNS1: 50/50 DIELECTRIC COATED PLATE BEAM SPLITTER 630 TO 660 NM COMES IN A TRIANGLE SHAPE EACH SIDE APPROX. 1" PRICE $20 ITEM # 45NS1 45 DEGREE RED REFLECTOR , PASSES 488 TO 532NM , CAN BE USED TO COMBINE RED AND GREEN/BLUE LASERS TO CREATE A WHITE LIGHT LASER. 1" SQ. PRICE $15 ITEM# PCINS1 PLANO/CONVEX LENS COATED FOR YAG 1064NM , AR COATED, 10MM DIA. NEW, ORIG. COST $250 OUR PRICE $100 ITEM# INFILTER : INTERFERENCE FILTERS USED FOR PASSING A PARTICULAR SPECTRAL LINE , 11.8 MM DIA. CAREFULLY REMOVED FROM MEDICAL EQUIPMENT AND WRAPPED IN LENSE PAPER. THE FOLLOWING WAVE LENGTHS ARE AVAILABLE. 523.5, 547.4 , 572.1, 512.9, 550.6, 488, 505.7 nm price $20 each. FOR A COMPLETE LINE OF NEW AND USED LASERS - OPTICS -ELECTRO OPTICS- LASER SHOWS ORDER A COMPLETE CATALOG AT MWKINDUSTRIES.COM TO: ORDER GO TO OUR WEB SITE MWKINDUSTRIES.COM {SECURE ORDERING SITE} QUESTIONS OR REMOVAL FROM MAILING LIST EMAIL: MWK@WORLDNET.ATT.NET MWK INDUSTRIES 1269 POMONA RD CORONA CA 91720 PHONE 909-278-0563 FAX 909-278-4887 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From gstein@exchange.microsoft.com Sun Dec 7 14:49:57 1997 From: gstein@exchange.microsoft.com (Greg Stein (Exchange)) Date: Sun, 7 Dec 1997 06:49:57 -0800 Subject: [DB-SIG] DB-API Spec. 1.1a1 Message-ID: <69D8143E230DD111B1D40000F8485840BCB62C@ED> I don't believe there is really any need for new date/time handling at the database module level. One of the purposes of the DBI module was to handle this specific problem. 1a) when a fetch is done, how do you differentiate a date from an integer or float? Using a tuple is possible here, but they are harder to work with than the integer/float (time_t) format. Instead, fetch returns an instance of dbi.dbiDate, with its "value" attribute set to an integer/float Python object. 1b) when an insert is done, how do you differentiate a date from something else? Again, you could use a tuple, but you could then run into a problem differentiating between inserting multiple dates vs. inserting multiple rows of one date each. The answer is using dbi.dbiDate instances and extracting the value attribute. Note: in most databases, you must know the input binding type a priori before the binding occurs. That is why you need to know the type before inserting. 2a) when a fetch is done, how do you diffentiate a string from a LONG/BLOB/whatever? Of course, representing those as a string is quite handy. This can go either way, but 2b (below) implies that you want to use a custom type: dbi.dbiRaw for these 2b) when an insert is done, you need to diffentiate between a string and a LONG/BLOB. Here, you definitely can't use a string. The answer is to use dbi.dbiRaw and extract the value from it. The mechanism of using custom types for dates and longs/blobs as indicators for insert (and partially for fetch) was solved by using the dbi module. I would recommend that if you want different date/time formats, that you simply implement new methods on the dbiDate instances. Better yet, just relegate that work to Python layers. Bill is quite on the mark when he says to avoid imposing extra work on database implementors. One single format is preferable. [ although, I'm not sure where the heck he was going with the date module concept since dbiDate represents the type that he's looking for. ] -g _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From raf@comdyn.com.au Mon Dec 8 00:19:56 1997 From: raf@comdyn.com.au (raf) Date: Mon, 8 Dec 1997 11:19:56 +1100 Subject: [DB-SIG] DB-API Spec. 1.1a1 Message-ID: <199712080019.LAA13351@mali.comdyn.com.au> [apologies to the one who got this twice] >Bill Tutt wrote: >> >> The "best way" for date/time formats is easy.. DON'T >> The reason you don't want to do this is because it imposes an uncessary >> requirement on the code that works with the database i.e. dealing with >> different date formats.. Thats just silly. it's also silly to impose a uniform time/date type on the time/date values across ALL databases IF such a type were to cause information loss. the sybase datetime datatype consists of 2 four byte integers. if that gets converted into something like a double or a unix-datetime (seconds since 1970) then the data has been corrupted. other databases probably have precise datetime types as well. if ONE type is to be used, it cannot be allowed to lose information under any circumstances. if this is impossible or would cause inefficiency when dealing with less demanding databases, then the dbimodule should only specify an interface, not a representation. that would have to be left to the modules that specialise it. raf _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Mon Dec 8 10:38:39 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Mon, 08 Dec 1997 11:38:39 +0100 Subject: [DB-SIG] DB-API Spec. 1.1a1 References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> Message-ID: <348BCE2F.2869F37E@uni-duesseldorf.de> Greg Stein (Exchange) wrote: > > I don't believe there is really any need for new date/time handling at > the database module level. One of the purposes of the DBI module was to > handle this specific problem. As Bill and Jim already pointed out, the current date/time handling in Python is fine when all you care about is a range from 1970 to 2038, but as soon as you want to handle dates beyond that range, you get into trouble. And there are still many around having been born earlier than 1970 ;-) Meaning that whenever you plan to do serious DB work (which will sooner or later deal with dates of birth), you cross the interface in some other way (well, maybe you're lucky and the t_time functions handle negative properly...). So a new date/time handling mechanism is due anyway. Of course, dbiDate should use this new type. As I understood the dbi definitions, the classes dbiDate and dbiRaw are meant as wrappers only -- for the sake of having type information around. So dbiDate would only pass through the date object and the DB interface can then make use of the C API for the new type which certainly is much easier to program than having to deal with 2 or 3 different formats, I agree. > 1a) when a fetch is done, how do you differentiate a date from an > integer or float? Using a tuple is possible here, but they are harder to > work with than the integer/float (time_t) format. Instead, fetch returns > an instance of dbi.dbiDate, with its "value" attribute set to an > integer/float Python object. > > 1b) when an insert is done, how do you differentiate a date from > something else? Again, you could use a tuple, but you could then run > into a problem differentiating between inserting multiple dates vs. > inserting multiple rows of one date each. The answer is using > dbi.dbiDate instances and extracting the value attribute. > Note: in most databases, you must know the input binding type a priori > before the binding occurs. That is why you need to know the type before > inserting. > > 2a) when a fetch is done, how do you diffentiate a string from a > LONG/BLOB/whatever? Of course, representing those as a string is quite > handy. This can go either way, but 2b (below) implies that you want to > use a custom type: dbi.dbiRaw for these > > 2b) when an insert is done, you need to diffentiate between a string and > a LONG/BLOB. Here, you definitely can't use a string. The answer is to > use dbi.dbiRaw and extract the value from it. > > The mechanism of using custom types for dates and longs/blobs as > indicators for insert (and partially for fetch) was solved by using the > dbi module. I don't have a problem with using the dbi module and do see its relevance for those DBs which don't provide a describe API for prepared executes, but in this special case I think we would all benefit from having an extra type around -- not only for interfacing to DBs, but also to implement other nifty things like e.g. financial time calculations. > I would recommend that if you want different date/time formats, that you > simply implement new methods on the dbiDate instances. Better yet, just > relegate that work to Python layers. Bill is quite on the mark when he > says to avoid imposing extra work on database implementors. One single > format is preferable. IMHO, this should be a date object on both input and output. > [ although, I'm not sure where the heck he was going with the date > module concept since dbiDate represents the type that he's looking for. > ] For those interested on the date/time subject, I recommend the calendar FAQ: http://www.pip.dknet.dk/~pip10160/calendar.html BTW: I'm working on a prototype for a such date type in Python. I'm not yet sure, but it seems that actually two types will emerge from it: one for fixed points in time and one to express time deltas. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From hannu@trust.ee Mon Dec 8 11:45:25 1997 From: hannu@trust.ee (Hannu Krosing) Date: Mon, 08 Dec 1997 13:45:25 +0200 Subject: [DB-SIG] DB-API Spec. 1.1a1 References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> <348BCE2F.2869F37E@uni-duesseldorf.de> Message-ID: <348BDDD4.CD050B73@sid.trust.ee> M.-A. Lemburg wrote: > Meaning that > whenever you plan to do serious DB work (which will sooner > or later deal with dates of birth), you cross the interface > in some other way (well, maybe you're lucky and the t_time > functions handle negative properly...). So a new date/time > handling mechanism is due anyway. Agreed > Of course, dbiDate should use this new type. It should also accept the current one (number of seconds since 1970). It can't be too difficult ac the new date(time) type must be able to convert from/to it anyway. > > The mechanism of using custom types for dates and longs/blobs as > > indicators for insert (and partially for fetch) was solved by using the > > dbi module. > > I don't have a problem with using the dbi module and do see > its relevance for those DBs which don't provide a describe API for > prepared executes, but in this special case I think we would all > benefit from having an extra type around -- not only for interfacing > to DBs, but also to implement other nifty things like e.g. financial > time calculations. > > > I would recommend that if you want different date/time formats, that you > > simply implement new methods on the dbiDate instances. Better yet, just > > relegate that work to Python layers. Bill is quite on the mark when he > > says to avoid imposing extra work on database implementors. One single > > format is preferable. > > IMHO, this should be a date object on both input and output. The problem is backward compatibility. To what extent do we need it? > For those interested on the date/time subject, I recommend > the calendar FAQ: > > http://www.pip.dknet.dk/~pip10160/calendar.html > > BTW: I'm working on a prototype for a such date type in Python. > I'm not yet sure, but it seems that actually two types will emerge > from it: one for fixed points in time and one to express > time deltas. You could check the date handling in postgres dbms (see http://www.PostgreSQL.org) At least the copyright terms seem to be compatible. They are in src/backend/utils/adt/{dt|dateime|date|timestamp}.c There are actually 2 families of date functions one t_time based and another more generic. They have three time types (not two as you plan) : fixed points in time (abstime) , time deltas (reltime), and time intervals (tinterval). Of course tinterval can be represented by just to abstimes (and then having different variants of intervals correspond to them (for 30/360, 30/365, real/365 etc.) Actually the financial time functions are a real can of worms and should be wekk thought out before making it public. Later we may be even able to persuade Guido to include the date type in core python distribution. It is the only datatype really missing from python now. Hannu _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From christian.egli@stest.ch Mon Dec 8 13:12:53 1997 From: christian.egli@stest.ch (Christian Egli) Date: 08 Dec 1997 14:12:53 +0100 Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) In-Reply-To: "M.-A. Lemburg"'s message of Mon, 08 Dec 1997 11:38:39 +0100 References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> <348BCE2F.2869F37E@uni-duesseldorf.de> Message-ID: >>>>> "Marc" == M -A Lemburg writes: Marc> As Bill and Jim already pointed out, the current date/time Marc> handling in Python is fine when all you care about is a range Marc> from 1970 to 2038, but as soon as you want to handle dates Marc> beyond that range, you get into trouble. Marc> BTW: I'm working on a prototype for a such date type in Marc> Python. I'm not yet sure, but it seems that actually two Marc> types will emerge from it: one for fixed points in time and Marc> one to express time deltas. I can't hold myself back any longer: Edward M. Reingold has written some fine functions relating to calendars which are included in the Emacs distribution. This code has been translated by himself to C++ and can be found under http://emr.cs.uiuc.edu/~reingold/papers/calendar/calendar.C. I tried to swig this code but had troubles with overloaded operators. But it was pretty straightforward to translate it into Python. Only a few of the requirements for a Date-Time type that Jim Fulton once stated in the db-sig are actually supported and obviously it is not implemented in C. But maybe some of this code could be scavenged for a C implementation or somebody manages to swig the above C++ code. This code is released as is. "It works for me". I don't claim it to be complete. Nor do I claim that it is the answer (or even an answer) to the current discussion in the db-sig. See also the TODO section in the code. ----------------cut here-------------------------------------------------------- #!/bin/env python """The following python code is translated from C++ code which is translated from the Lisp code in ``Calendrical Calculations'' by Nachum Dershowitz and Edward M. Reingold, Software---Practice & Experience, vol. 20, no. 9 (September, 1990), pp. 899--928. The C++ code can be obtained from http://emr.cs.uiuc.edu/~reingold/papers/calendar/calendar.C This code is in the public domain, but any use of it should publically acknowledge its source. Classes GregorianDate, JulianDate, IsoDate, IslamicDate, and HebrewDate TODO: As Jim Fulton once noted in the db-sig: > It would be helpful to have a standard date-time implementation for > use in Python database implementations (and elsewhere, of course). > > I think that the date-time implementation should: > > 1. Support conversion from strings in a very wide variety of formats > (e.g. 'Oct, 1, 1994 12:34am EST', '1994/10/1 00:34:21.456') > > 2. Support subtraction of date-times, and addition and > subtraction of dates and numbers. > > 3. Store dates efficiently. > > 4. Store dates immutably. > > 5. Represent dates to a specified minimum precision > (e.g. milliseconds). > > 6. Handle all dates in the Gregorian calendar. (e.g. there should > not be problems storing dates from the 18th or 21st centurys.) > > 7. Provide read-access to date-components (e.g. year, month, second, > day-of-week, etc.) > > I'm afraid the implementation should also address issues like: > > 8. Support for time-zones, > > 9. Support for daylight-savings time. This implementation of Date only fullfills Requirement 2 and 6 and to some degree 7. """ __version__ = "1.5" DayName = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday") # Absolute dates class Date: """Absolute date means the number of days elapsed since the Gregorian date Sunday, December 31, 1 BC. (Since there was no year 0, the year following 1 BC is 1 AD.) Thus the Gregorian date January 1, 1 AD is absolute date number 1. """ reprFormat = "%(month)s/%(day)s/%(year)s" def __init__(self, absoluteDate = None): self.abs = absoluteDate def __repr__(self): return self.reprFormat % self.__dict__ def __cmp__(self, other): """Comparison of Dates with Dates returns -1 if self < other, 0 if self == other or 1 if self > other. Comparison of Dates with any other type raises a TypeError exception. """ if (type(other) == types.InstanceType and issubclass(other.__class__, Date)): if self.absolute() < other.absolute(): return -1 elif self.absolute() > other.absolute(): return 1 else: return 0 else: raise TypeError, 'Comparison of Dates is only allowed with Dates' def __add__(self, other): """Addition of Dates with numbers (int and long) returns a new Date. Addition of Dates with any other type raises a TypeError exception. """ import types if type(other) in [types.IntType, types.LongType]: return self.__class__(self.absolute() + other) else: raise TypeError, 'Addition of Dates is only allowed with numbers' __radd__ = __add__ def __sub__(self, other): """Subtraction of Dates with numbers (int and long) returns a new Date. Subtraction of Dates with Dates returns an absolute difference in days. Subtraction of Dates with any other type raises a TypeError exception.""" import types if (type(other) == types.InstanceType and issubclass(other.__class__, Date)): return self.absolute() - other.absolute() elif type(other) in [types.IntType, types.LongType]: return self.__class__(self.absolute() - other) else: raise TypeError, 'Subtraction of Dates is only allowed with Dates or numbers' __rsub__ = __sub__ def XdayOnOrBefore(d, x): """Absolute date of the x-day on or before absolute date d. x=0 means Sunday, x=1 means Monday, and so on. "Absolute date" means the number of days elapsed since the Gregorian date Sunday, December 31, 1 BC. (Since there was no year 0, the year following 1 BC is 1 AD.) Thus the Gregorian date January 1, 1 AD is absolute date number 1. """ return (d - ((d - x) % 7)) # Gregorian dates def LastDayOfGregorianMonth(month, year): """Compute the last date of the month for the Gregorian calendar.""" if (month == 2): if ((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0)): return 29 else: return 28 elif ((month == 4) or (month == 6) or (month == 9) or (month == 11)): return 30 else: return 31 def NthXday(n, x, month, year, day = 0): """The Gregorian date of nth x-day in month, year before/after optional day. x = 0 means Sunday, x = 1 means Monday, and so on. If n<0, return the nth x-day before month day, year (inclusive). If n>0, return the nth x-day after month day, year (inclusive). If day is omitted or 0, it defaults to 1 if n>0, and month's last day otherwise.""" if (n > 0): if (day == 0): day = 1 # default for positive n absDate = GregorianDate(day, month, year).absolute() return GregorianDate((7 * (n - 1)) + XdayOnOrBefore(6 + absDate, x)) else: if (day == 0): day = LastDayOfGregorianMonth(month, year) # default for negative n absDate = GregorianDate(day, month, year).absolute() return GregorianDate((7 * (n + 1)) + XdayOnOrBefore(absDate, x)) class GregorianDate(Date): """The Gregorian Calendar is the present day civil calendar in much of the world. It was instituted by Pope Gregory when he corrected the Julian Calendar by proclaiming that Thursday, October 4, 1582 C.E. would be followed by Friday, October 15, 1582 C.E. thus skipping 10 days. Over time most of the countries of world adopted this calendar. It corrected for the problems of the Julian Calendar by introducing a more complicated leap year structure: Year y is a leap year if it is divisible by 400 or it is a year that is divisible by 4 and not divisible by 100. """ def __init__(self, d, m = 0, y = 0): """year # 1... month # 1 == January, ..., 12 == December day # 1..LastDayOfGregorianMonth(month, year) """ if ((m != 0) and (y != 0)): Date.__init__(self) self.month = m self.day = d self.year = y else: Date.__init__(self, d) # Computes the Gregorian date from the absolute date. # Search forward year by year from approximate year year = d/366 while (d >= GregorianDate(1,1,year+1).absolute()): year = year + 1 # Search forward month by month from January month = 1 while (d > GregorianDate(LastDayOfGregorianMonth(month,year), month, year).absolute()): month = month + 1 day = d - GregorianDate(1,month,year).absolute() + 1 self.year, self.month, self.day = year, month, day def absolute(self): """Computes the absolute date from the Gregorian date. "Absolute date" means the number of days elapsed since the Gregorian date Sunday, December 31, 1 BC. (Since there was no year 0, the year following 1 BC is 1 AD.) Thus the Gregorian date January 1, 1 AD is absolute date number 1. """ if self.abs: return self.abs N = self.day # days this month year = self.year month = self.month for m in range(month - 1, 0, -1): # days in prior months this year N = N + LastDayOfGregorianMonth(m, year) self.abs = (N # days this year + 365 * (year - 1) # days in previous years ignoring leap days + (year - 1)/4 # Julian leap days before this year... - (year - 1)/100 # ...minus prior century years... + (year - 1)/400) # ...plus prior years divisible by 400 return self.abs # Julian dates JulianEpoch = -2 # Absolute date of start of Julian calendar def LastDayOfJulianMonth(month, year): """Compute the last date of the month for the Julian calendar.""" if (month == 2): if ((year % 4) == 0): return 29 else: return 28 elif ((month == 4) or (month == 6) or (month == 9) or (month == 11)): return 30 else: return 31 class JulianDate(Date): """The Julian Calendar was the predecessor to the Gregorian Calendar as the civil calendar for much of the world. It has a very simple leap year structure, all years divisible by 4 are leap years. This is close to true but deviates from the average length of the solar year over time. Thus the need for the 10 day correction in 1582. """ def __init__(self, d, m = 0, y = 0): """year # 1... month # 1 == January, ..., 12 == December day # 1..LastDayOfJulianMonth(month, year) """ if ((m != 0) and (y != 0)): Date.__init__(self) self.month = m self.day = d self.year = y else: Date.__init__(self, d) # Computes the Julian date from the absolute date. # Search forward year by year from approximate year year = (d + JulianEpoch)/366 while (d >= JulianDate(1,1,year+1).absolute()): year = year + 1 # Search forward month by month from January month = 1 while (d > JulianDate(LastDayOfJulianMonth(month,year), month, year).absolute()): month = month + 1 day = d - JulianDate(1,month,year).absolute() + 1 self.year, self.month, self.day = year, month, day def absolute(self): """Computes the absolute date from the Julian date. "Absolute date" means the number of days elapsed since the Gregorian date Sunday, December 31, 1 BC. (Since there was no year 0, the year following 1 BC is 1 AD.) Thus the Gregorian date January 1, 1 AD is absolute date number 1. """ if self.abs: return self.abs N = self.day # days this month year = self.year for m in range(self.month - 1, 0, - 1): # days in prior months this year N = N + LastDayOfJulianMonth(m, year) self.abs = (N # days this year + 365 * (year - 1) # days in previous years ignoring leap days + (year - 1)/4 # leap days before this year... + JulianEpoch) # days elapsed before absolute date 1 return self.abs # ISO dates class IsoDate(Date): """The International Organization for Standardization (ISO) produced a calendar that is popular in some European countries. A date is specified as the ordinal day in the week and the `calendar week' of the Gregorian year. The `ISO year' corresponds approximately to the Gregorian year, but weeks start on Monday and end on Sunday. The first week of the ISO year is the first such week in which at least 4 days are in a year. The ISO commercial DATE has the form (week day year) in which week is in the range 1..52 and day is in the range 0..6 (1 = Monday, 2 = Tuesday, ..., 0 = Sunday). """ reprFormat = "%(week)s-%(day)s-%(year)s" def __init__(self, d, w = 0, y = 0): """year # 1... week # 1..52 or 53 day # 1..7 """ if ((w != 0) and (y != 0)): Date.__init__(self) self.week = w self.day = d self.year = y else: Date.__init__(self, d) # Computes the ISO date from the absolute date. year = GregorianDate(d - 3).year if (d >= IsoDate(1,1,year+1).absolute()): year = year + 1 if ((d % 7) == 0): day = 7 # Sunday else: day = d % 7 # Monday..Saturday week = 1 + (d - IsoDate(1,1,year).absolute()) / 7 self.year, self.week, self.day = year, week, day def absolute(self): """Computes the absolute date from the ISO date. """ if self.abs: return self.abs self.abs = (XdayOnOrBefore(GregorianDate(4,1,self.year).absolute(),1) # days in prior years + 7 * (self.week - 1) # days in prior weeks this year + (self.day - 1)) # prior days this week return self.abs # Islamic dates IslamicEpoch = 227014 # Absolute date of start of Islamic calendar def IslamicLeapYear(year): """True if year is an Islamic leap year""" if ((((11 * year) + 14) % 30) < 11): return 1 else: return 0 def LastDayOfIslamicMonth(month, year): """Last day in month during year on the Islamic calendar.""" if (((month % 2) == 1) or ((month == 12) and IslamicLeapYear(year))): return 30 else: return 29 class IslamicDate(Date): """This Islamic Calendar is a strictly lunar calendar making it very easy to calculate. No attempt is made to keep the months in line with the seasons of the year. Instead they wander through the seasons as the years go by. As in the Hebrew Calendar the day begins at sunset which we again take to be 6pm local time. Unfortunately the calculations provided here are only approximate. Unlike the Hebrew Calendar there are many more disparate forms of the Islamic Calendar. Even worse, much of the Islamic world still relies on proclamations of the new moon by religious authorities instead of on calculations. Thus the routines can be in error by a day or two from what is actually observed in different parts of the Islamic world. """ def __init__(self, d, m = 0, y = 0): """year # 1... month # 1..13 (12 in a common year) day # 1..LastDayOfIslamicMonth(month,year) """ if ((m != 0) and (y != 0)): Date.__init__(self) self.month = m self.day = d self.year = y else: Date.__init__(self, d) # Computes the Islamic date from the absolute date. if (d <= IslamicEpoch): # Date is pre-Islamic month = 0 day = 0 year = 0 else: # Search forward year by year from approximate year year = (d - IslamicEpoch) / 355 while (d >= IslamicDate(1,1,year+1).absolute()): year = year + 1 # Search forward month by month from Muharram month = 1 while (d > IslamicDate(LastDayOfIslamicMonth(month,year), month, year).absolute()): month = month + 1 day = d - IslamicDate(1,month,year).absolute() + 1 self.year, self.month, self.day = year, month, day def absolute(self): """Computes the absolute date from the Islamic date. "Absolute date" means the number of days elapsed since the Gregorian date Sunday, December 31, 1 BC. (Since there was no year 0, the year following 1 BC is 1 AD.) Thus the Gregorian date January 1, 1 AD is absolute date number 1. """ if self.abs: return self.abs self.abs = (self.day # days so far this month + 29 * (self.month - 1) # days so far... + self.month/2 # ...this year + 354 * (self.year - 1) # non-leap days in prior years + (3 + (11 * self.year)) / 30 # leap days in prior years + IslamicEpoch) # days before start of calendar return self.abs # Hebrew dates HebrewEpoch = -1373429 # Absolute date of start of Hebrew calendar def HebrewLeapYear(year): """True if year is an Hebrew leap year""" if ((((7 * year) + 1) % 19) < 7): return 1 else: return 0 def LastMonthOfHebrewYear(year): """Last month of Hebrew year.""" if (HebrewLeapYear(year)): return 13 else: return 12 def HebrewCalendarElapsedDays(year): """Number of days elapsed from the Sunday prior to the start of the Hebrew calendar to the mean conjunction of Tishri of Hebrew year.""" MonthsElapsed = ((235 * ((year - 1) / 19)) # Months in complete cycles so far. + (12 * ((year - 1) % 19)) # Regular months in this cycle. + (7 * ((year - 1) % 19) + 1) / 19) # Leap months this cycle PartsElapsed = 204 + 793 * (MonthsElapsed % 1080) HoursElapsed = (5 + 12 * MonthsElapsed + 793 * (MonthsElapsed / 1080) + PartsElapsed / 1080) ConjunctionDay = 1 + 29 * MonthsElapsed + HoursElapsed / 24 ConjunctionParts = 1080 * (HoursElapsed % 24) + PartsElapsed % 1080 if ((ConjunctionParts >= 19440) # If new moon is at or after midday, or (((ConjunctionDay % 7) == 2) # ...or is on a Tuesday... and (ConjunctionParts >= 9924) # at 9 hours, 204 parts or later... and not (HebrewLeapYear(year))) # ...of a common year, or (((ConjunctionDay % 7) == 1) # ...or is on a Monday at... and (ConjunctionParts >= 16789) # 15 hours, 589 parts or later... and (HebrewLeapYear(year - 1)))): # at the end of a leap year # Then postpone Rosh HaShanah one day AlternativeDay = ConjunctionDay + 1 else: AlternativeDay = ConjunctionDay if (((AlternativeDay % 7) == 0) # If Rosh HaShanah would occur on Sunday, or ((AlternativeDay % 7) == 3) # or Wednesday, or ((AlternativeDay % 7) == 5)): # or Friday # Then postpone it one (more) day return (1+ AlternativeDay) else: return AlternativeDay def DaysInHebrewYear(year): """Number of days in Hebrew year.""" return ((HebrewCalendarElapsedDays(year + 1)) - (HebrewCalendarElapsedDays(year))) def LongHeshvan(year): """True if Heshvan is long in Hebrew year.""" if ((DaysInHebrewYear(year) % 10) == 5): return 1 else: return 0 def ShortKislev(year): """True if Kislev is short in Hebrew year.""" if ((DaysInHebrewYear(year) % 10) == 3): return 1 else: return 0 def LastDayOfHebrewMonth(month, year): """Last day of month in Hebrew year.""" if ((month == 2) or (month == 4) or (month == 6) or ((month == 8) and not (LongHeshvan(year))) or ((month == 9) and ShortKislev(year)) or (month == 10) or ((month == 12) and not (HebrewLeapYear(year))) or (month == 13)): return 29 else: return 30 class HebrewDate(Date): """The Hebrew Calendar is one of the most complicated calendars. It attempts to keep the months strictly lunar cycles and still be in sync with a solar year. On top of this are strict guidelines as to what days certain religious events must occur. It used to be the case that a new month was decreed when a new moon was ``sighted''. For the most part this has been turned over to astronomical calculations which are more accurate. The new day begins at sunset. For our purposes we start new days at 6pm local time. This is a good enough approximation to when the sun sets. """ def __init__(self, d, m = 0, y = 0): """year # 1... month # 1..LastMonthOfHebrewYear(year) day # 1..LastDayOfHebrewMonth(month, year) """ if ((m != 0) and (y != 0)): Date.__init__(self) self.month = m self.day = d self.year = y else: Date.__init__(self, d) # Computes the Hebrew date from the absolute date. year = (d - HebrewEpoch) / 366 # Approximation from below. # Search forward for year from the approximation. while (d >= HebrewDate(1,7,year + 1).absolute()): year = year + 1 # Search forward for month from either Tishri or Nisan. if (d < HebrewDate(1, 1, year).absolute()): month = 7 # Start at Tishri else: month = 1 # Start at Nisan while (d > HebrewDate(LastDayOfHebrewMonth(month,year), month, year).absolute()): month = month + 1 # Calculate the day by subtraction. day = d - HebrewDate(1, month, year).absolute() + 1 self.year, self.month, self.day = year, month, day def absolute(self): """Computes the absolute date of Hebrew date. "Absolute date" means the number of days elapsed since the Gregorian date Sunday, December 31, 1 BC. (Since there was no year 0, the year following 1 BC is 1 AD.) Thus the Gregorian date January 1, 1 AD is absolute date number 1. """ if self.abs: return self.abs DayInYear = self.day # Days so far this month. if (self.month < 7): # Before Tishri, so add days in prior months # this year before and after Nisan. m = 7 while (m <= (LastMonthOfHebrewYear(self.year))): DayInYear = DayInYear + LastDayOfHebrewMonth(m, self.year) m = m + 1 m = 1 while (m < self.month): DayInYear = DayInYear + LastDayOfHebrewMonth(m, self.year) m = m + 1 else: # Add days in prior months this year m = 7 while (m < self.month): DayInYear = DayInYear + LastDayOfHebrewMonth(m, self.year) m = m + 1 self.abs = (DayInYear + (HebrewCalendarElapsedDays(self.year)# Days in prior years. + HebrewEpoch)) # Days elapsed before absolute date 1. return self.abs if __name__ == "__main__": import string while (1): y = string.atoi(raw_input("Enter year (>0): ")) m = string.atoi(raw_input("Enter month (1..12): ")) d = string.atoi(raw_input("Enter day (1..%s ): " % LastDayOfGregorianMonth(m, y))) g = GregorianDate(d,m,y) a = g.absolute() print "%s = %s = %s" % (g, a, DayName[g.absolute() % 7]) g2 = g + 1 a = g2.absolute() print "%s + 1 = %s = %s" % (g, g2, a) g = GregorianDate(a) a = g.absolute() print "= gregorian date %s = absolute date %s " % (g, a) j = JulianDate(a) a = j.absolute() print "= julian date %s = absolute date %s" % (j, a) i = IsoDate(a) a = i.absolute() print "= iso date %s = absolute date %s " % (i,a) h = HebrewDate(a) a = h.absolute() print "= hebrew date %s = absolute date %s" % (h, a) isl= IslamicDate(a) a = isl.absolute() print "= islamic date %s = absolute date %s" % (isl, a) -- Christian Egli Switching Test Solutions AG, Friesenbergstr. 75, CH-8055 Zuerich _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Mon Dec 8 14:14:44 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Mon, 08 Dec 1997 15:14:44 +0100 Subject: [DB-SIG] DB-API Spec. 1.1a1 References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> <348BCE2F.2869F37E@uni-duesseldorf.de> <348BDDD4.CD050B73@sid.trust.ee> Message-ID: <348C00D3.31071951@uni-duesseldorf.de> Hannu Krosing wrote: > > M.-A. Lemburg wrote: > > > Of course, dbiDate should use this new type. > > It should also accept the current one (number of seconds since 1970). It can't > be too difficult ac the new date(time) type must be able to convert from/to it > anyway. dbiDate could be used to convert the new type into a time_t value, raising an exception in case this doesn't work. > > > I would recommend that if you want different date/time formats, that you > > > simply implement new methods on the dbiDate instances. Better yet, just > > > relegate that work to Python layers. Bill is quite on the mark when he > > > says to avoid imposing extra work on database implementors. One single > > > format is preferable. > > > > IMHO, this should be a date object on both input and output. > > The problem is backward compatibility. To what extent do we need it? As far as I understand the Python C API, PyFloat_AsDouble() is the one function that C code should use to access an object as a number. This function looks at the tp_as_number-slot and then calls nb_float, so I guess all that's needed is to provide those hooks returning a time_t value. So input shouldn't be a big problem. On the output side old modules will still give you integers though -- code written for the new style interface will have to watch out for this. Old code will expect a time_t value, so the above applies to this case too. > > For those interested on the date/time subject, I recommend > > the calendar FAQ: > > > > http://www.pip.dknet.dk/~pip10160/calendar.html > > > > BTW: I'm working on a prototype for a such date type in Python. > > I'm not yet sure, but it seems that actually two types will emerge > > from it: one for fixed points in time and one to express > > time deltas. > > You could check the date handling in postgres dbms (see > http://www.PostgreSQL.org) > At least the copyright terms seem to be compatible. Thanks, I'll have a look. > They are in src/backend/utils/adt/{dt|dateime|date|timestamp}.c > > There are actually 2 families of date functions one t_time based and another > more generic. > > They have three time types (not two as you plan) : fixed points in time > (abstime) , time deltas (reltime), and time intervals (tinterval). Of course > tinterval can be represented by just to abstimes (and then having different > variants of intervals correspond to them (for 30/360, 30/365, real/365 etc.) > > Actually the financial time functions are a real can of worms and should be > wekk thought out before making it public. Later we may be even able to > persuade Guido to include the date type in core python distribution. It is the > only datatype really missing from python now. You're probably right... putting too much on the agenda kills motivation :-) -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Mon Dec 8 15:11:54 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Mon, 08 Dec 1997 16:11:54 +0100 Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> <348BCE2F.2869F37E@uni-duesseldorf.de> Message-ID: <348C0E3A.20E97863@uni-duesseldorf.de> [Lots of code from Christian Egli] What an impressive list of date formats, thanks. I think we should (at first) stick to Gregorian and Julien dates for input/output methods. Your "absolute date" basis seems to be a reasonable internal format for the date integer. Time could be encoded as double expressing seconds since midnight. This is pretty accurate and allows for leap seconds etc. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From aaron_watters@classic.msn.com Mon Dec 8 16:47:06 1997 From: aaron_watters@classic.msn.com (aaron watters) Date: Mon, 8 Dec 97 16:47:06 UT Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) Message-ID: Didn't Tim Peters or someone do a lot of Python-date work? This is a pretty important discussion, really. I'd like to see the specification for a perfectly general Date data type with a pure Python implementation. As you know :) I'm developing a pure Python database engine, so dependencies on C++ code (which may not even port to many platforms) is verboten for me. There's gotta be a good http ref out there for std date handling... * Aaron Watters (http://www.pythonpros.com) Ps: couldn't find anything at python.org. Saw lots of references to stuff that didn't work last time I tried it :). A lot of stuff that does work is nowhere to be found of course, oh well. _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From hannu@trust.ee Mon Dec 8 17:47:38 1997 From: hannu@trust.ee (Hannu Krosing) Date: Mon, 08 Dec 1997 19:47:38 +0200 Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> <348BCE2F.2869F37E@uni-duesseldorf.de> Message-ID: <348C32BA.E2272B2F@sid.trust.ee> Christian Egli wrote: > >>>>> "Marc" == M -A Lemburg writes: > > Marc> As Bill and Jim already pointed out, the current date/time > Marc> handling in Python is fine when all you care about is a range > Marc> from 1970 to 2038, but as soon as you want to handle dates > Marc> beyond that range, you get into trouble. > > Marc> BTW: I'm working on a prototype for a such date type in > Marc> Python. I'm not yet sure, but it seems that actually two > Marc> types will emerge from it: one for fixed points in time and > Marc> one to express time deltas. > > I can't hold myself back any longer: Good ! > Edward M. Reingold has written some fine functions relating to > calendars which are included in the Emacs distribution. This code has > been translated by himself to C++ and can be found under > http://emr.cs.uiuc.edu/~reingold/papers/calendar/calendar.C. I tried > to swig this code but had troubles with overloaded operators. But it > was pretty straightforward to translate it into Python. > > Only a few of the requirements for a Date-Time type that Jim Fulton > once stated in the db-sig are actually supported and obviously it is > not implemented in C. But maybe some of this code could be scavenged > for a C implementation or somebody manages to swig the above C++ code. > > This code is released as is. "It works for me". I don't claim it to be > complete. Nor do I claim that it is the answer (or even an answer) to > the current discussion in the db-sig. See also the TODO section in the > code. > > ----------------cut here-------------------------------------------------------- As it is a very nice module indeed and might be used by several people ;), we should agree what to call this module (I would propose WorldDates.py, unless it already has some nice name), Under 1.5 hierarchy different calendars could of course be split into separate submodules under Date. > #!/bin/env python > Hannu Krosing _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From mclay@nist.gov Mon Dec 8 18:50:23 1997 From: mclay@nist.gov (Michael McLay) Date: Mon, 8 Dec 1997 13:50:23 -0500 Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) In-Reply-To: <348C32BA.E2272B2F@sid.trust.ee> References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> <348BCE2F.2869F37E@uni-duesseldorf.de> <348C32BA.E2272B2F@sid.trust.ee> Message-ID: <199712081850.NAA18210@fermi.eeel.nist.gov> Hannu Krosing writes: > > As it is a very nice module indeed and might be used by several people ;), we should agree what to call > this module (I would propose WorldDates.py, unless it already has some nice name), > > Under 1.5 hierarchy different calendars could of course be split into separate submodules under Date. What other kinds of modules might eventually be in the date package? Hmm, maybe other date standards would have their own modules, i.e. date.iec, date.iso, date.eeel, date.sql, date.ansi, date.posix... Instead of date.WorldDates perhaps use date.world or maybe date.general. Michael _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From magnus.lycka@tripnet.se Mon Dec 8 20:27:16 1997 From: magnus.lycka@tripnet.se (Magnus Lycka) Date: Mon, 08 Dec 1997 21:27:16 +0100 Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) In-Reply-To: <348C0E3A.20E97863@uni-duesseldorf.de> References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> <348BCE2F.2869F37E@uni-duesseldorf.de> Message-ID: <3.0.1.32.19971208212716.0082b230@mail1.tripnet.se> At 16:11 1997-12-08 +0100, M.-A. Lemburg wrote: >[Lots of code from Christian Egli] > >What an impressive list of date formats, thanks. I think we >should (at first) stick to Gregorian and Julien dates for >input/output methods. Your "absolute date" basis seems to be >a reasonable internal format for the date integer. Time >could be encoded as double expressing seconds since midnight. >This is pretty accurate and allows for leap seconds etc. In Sweden we often use week numbers of the ISO type, but only when we refer to a particular week, not a specific day. For instance, a reasonably complete Swedish version of the unix cal(1) program would look more or less like this: $ cal 12 1997 December 1997 Vecka M=E5 Ti On To Fr L=F6 S=F6 49 1 2 3 4 5 6 7 50 8 9 10 11 12 13 14 51 15 16 17 18 19 20 21 52 22 23 24 25 26 27 28 (98)1 29 30 31 Note that ISO week numbers are neither %U nor %W in the unix date(1) command, but week 1 is the first week that has at least 4 days in January. In other words, week 1998-01 starts in december 1997, and week 1998-53 ends in January 1999. For me, this doesn't feel like it should be a class of it's own though. A date is a date is a date. I'd just like a method to extract the year/week number from a gregorian date, but maybe I just haven't gotten used to=20 the idea of making this an independent class. Either way, I don't think this has a lot to do with the DBI. As long as the DBI supplies a consistent date type or class I can have what ever methods I want in external (locale) classes. Maybe those classes should just have generic get/set functions =E0= la unix date(1) or C's strftime with a default set through locale. (Maybe we could just add ISO week as %v. Then I would be happy, but the problem is= that around the new year %Y and %y might show the wrong year, so we need two more year flags, or %v returning 199750 this week.) I suppose it's understandable that for instance Oracles SQL which has= evolved into a more extensive programming language and is used for ad hoq generation of reports etc support advanced date formatting, but if we write programs in a full language like Python we have no reason to mix data entry or= display functionality with storage. In other words, lets have nice date formatting functions, but not in the DBI. To be honest I don't care a bit about dates several hundred years ago, so for me, we can skip Julian dates. If there are people who are interested in Arabic, Hebrew, Buddhist calendars, fine, they are in use, but Julian dates are mainly useful for time span that is far outside any relevant use for administrative systems, but far to tiny to be useful for geologists etc. (On the other hand, if Julian here should be interpreted as in unix (%j) I agreee that that can be a useful way of handling Gregorian calendar dates.) Again, this is really not an issue for the DBI though. I agree that dates (and timestamps) could be standard Python types. I want my databases (and database interfaces) to recognize a date format and a timestamp format. I don't see a point in time-interval formats, as Hannu mentioned, and I haven't seen them in the databases I've used. In for instance Informix there is some kind of time interval format, but what that means is that you can decide what the resoultion and span of the type should be, for instance from minutes to hours, meaning that the smallest value you can store is 1 minute, and the largest is 23 hours and 59 minutes. I want to be able to get an integer representing days by subtracting a date from another, and by adding or subtracting an integer to/from a date I want to get another date.=20 I want to be able to do corresponding things with timestamps, but I'm not sure what types I want here. I think the suggestion above is OK. Maybe we could simply decide that if an integer is added to or subtracted from a date or timestamp, it's a number of days, and if the same thing is done with a=20 float, it's a number of seconds. That might not be extremely intuitive, but= =20 it's simple. Converting to dates from hand entered strings in all sorts of formats is a big mess that should be kept out of a database interface. For instance 3/4/5 might at least mean three things (if we agree on which century we refer to): 3 Apr 2005, 4 Mar 2005 or 5 Apr 2003. This should be handled by L=F6wis locale stuff. Magnus -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From tismer@appliedbiometrics.com Tue Dec 9 02:07:10 1997 From: tismer@appliedbiometrics.com (Christian Tismer) Date: Tue, 09 Dec 1997 03:07:10 +0100 Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> <348BCE2F.2869F37E@uni-duesseldorf.de> <3.0.1.32.19971208212716.0082b230@mail1.tripnet.se> Message-ID: <348CA7CB.DA7EDC82@appliedbiometrics.com> Magnus Lycka wrote: > At 16:11 1997-12-08 +0100, M.-A. Lemburg wrote: > >[Lots of code from Christian Egli] > > > >What an impressive list of date formats, thanks. I think we > >should (at first) stick to Gregorian and Julien dates for > >input/output methods. Your "absolute date" basis seems to be > >a reasonable internal format for the date integer. Time > >could be encoded as double expressing seconds since midnight. > >This is pretty accurate and allows for leap seconds etc. Yes please.I don't care of any-alian dates at all. I just have to usedatabases of people who live now or some years ago. This is what I have to deal with, and I think it is true for a lot of us. > ... > For me, this doesn't feel like it should be a class of it's own > though. > A date is a date is a date. I'd just like a method to extract the > year/week > number from a gregorian date, but maybe I just haven't gotten used to > the idea of making this an independent class. Either way, I don't > think > this has a lot to do with the DBI. As long as the DBI supplies a > consistent Right. DBI should handle dates, but not try to implement them. > date type or class I can have what ever methods I want in external > (locale) > classes. Maybe those classes should just have generic get/set > functions ` la > unix date(1) or C's strftime with a default set through locale. (Maybe > we > could just add ISO week as %v. Then I would be happy, but the problem > is that > around the new year %Y and %y might show the wrong year, so we need > two more > year flags, or %v returning 199750 this week.) > > I suppose it's understandable that for instance Oracles SQL which has > evolved > into a more extensive programming language and is used for ad hoq > generation > of reports etc support advanced date formatting, but if we write > programs > in a full language like Python we have no reason to mix data entry or > display > functionality with storage. In other words, lets have nice date > formatting > functions, but not in the DBI. I think this is write. Let's try to carry a date, which a database gives us,around, and ok. The more interpretation takes place, the worse. ... Dates are not an easy theme. And also they are not very popular. The people who are actually dealing with it, don't have the problem to move between different calendars. They simply want to see their own birthdate as a native date constant:-) (god am I old). Wha about this: KISS, but no simpler? cheers - pirx _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Tue Dec 9 12:31:16 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Tue, 09 Dec 1997 13:31:16 +0100 Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> <348BCE2F.2869F37E@uni-duesseldorf.de> <3.0.1.32.19971208212716.0082b230@mail1.tripnet.se> Message-ID: <348D3A14.4684AAD9@uni-duesseldorf.de> Magnus Lycka wrote: > > [ISO dates] > > For me, this doesn't feel like it should be a class of it's own though. > A date is a date is a date. I'd just like a method to extract the year/week > number from a gregorian date, but maybe I just haven't gotten used to > the idea of making this an independent class. Either way, I don't think > this has a lot to do with the DBI. As long as the DBI supplies a consistent > date type or class I can have what ever methods I want in external (locale) > classes. Maybe those classes should just have generic get/set functions à la > unix date(1) or C's strftime with a default set through locale. (Maybe we > could just add ISO week as %v. Then I would be happy, but the problem is that > around the new year %Y and %y might show the wrong year, so we need two more > year flags, or %v returning 199750 this week.) I'll have a (proto-)type for date/time handling ready in a few days. It uses Christian Egli's absolute date as internal date repesentation (making it compatible to his module) and seconds since midnight as time basis. The internal calendar used is the Gregorian, all other notations/calendars can interface to it via the absolute date which can easily be extracted from Christian's objects. Right now, I'm curious what you think about the time handling. We are bound to stumble into daylight savings time here + time zones which both are hard to handle. While the time zone can be deduced from time.timezone, the DST can only be guessed at. There are basically two options: 1. use GM time (AKA Zulu time AKA UTC) as internal basis and have some external method deduce the DST & time zone 2. store whatever the user gives to the object and return it in the same way Option 1 makes date/time calculations accurate to the extent provided by the external method (i.e. if it knows exactly when DST gets switched and what the time zone offset is, everything should work accurate to the microsecond). Option 2 can produce date/time calculation errors of up to an hour, but is pretty simple to use. > Again, this is really not an issue for the DBI though. I agree that dates > (and timestamps) could be standard Python types. Which is what we are aiming at... well, at least I am :-) [This isn't exactly the right place to discuss all this, but the main list is just too noisy so I'll continue here if noone objects] > Converting to dates from hand entered strings in all sorts of formats is > a big mess that should be kept out of a database interface. For instance > 3/4/5 might at least mean three things (if we agree on which century we > refer to): 3 Apr 2005, 4 Mar 2005 or 5 Apr 2003. This should be handled > by Löwis locale stuff. Conversion from date/time to strings is left to strftime(). The other way around could be handled by an elaborate module written in Python (something a la Skip's date.py) -- it's much too messy to get written in C. In the end, we could wrap everything up in a nice package... but there's still a long way to go I'm afraid. In the meantime, I've put together mxODBC version 0.5, a preliminary release which knows how to handle both date/time tuples and time_t values. This will eventually be changed to the use the new type in a next release. Note that the module does "tuple recognition" for date/time on cursor.execute() input and outputs these as indicated by the cursor variable cursor.datetimeformat. The release is mainly meant to test portability to Win32. I've included many suggestions from Christian Tismer, but can't test them myself. http://starship.skyport.net/~lemburg/mxODBC.html -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From hannu@trust.ee Tue Dec 9 13:43:05 1997 From: hannu@trust.ee (Hannu Krosing) Date: Tue, 09 Dec 1997 15:43:05 +0200 Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) References: <69D8143E230DD111B1D40000F8485840BCB62C@ED> <348BCE2F.2869F37E@uni-duesseldorf.de> <3.0.1.32.19971208212716.0082b230@mail1.tripnet.se> <348D3A14.4684AAD9@uni-duesseldorf.de> Message-ID: <348D4AE8.8085A90@sid.trust.ee> M.-A. Lemburg wrote: > > Again, this is really not an issue for the DBI though. I agree that dates > > (and timestamps) could be standard Python types. > > Which is what we are aiming at... well, at least I am :-) [This isn't > exactly the right place to discuss all this, but the main list is > just too noisy so I'll continue here if noone objects] Seems that the date type is most often required by the same people who use the DBI so it may not be entirely wrong place. > > Converting to dates from hand entered strings in all sorts of formats is > > a big mess that should be kept out of a database interface. For instance > > 3/4/5 might at least mean three things (if we agree on which century we > > refer to): 3 Apr 2005, 4 Mar 2005 or 5 Apr 2003. This should be handled > > by Löwis locale stuff. > > Conversion from date/time to strings is left to strftime(). The > other way around could be handled by an elaborate module written > in Python (something a la Skip's date.py) -- it's much too messy > to get written in C. The most foolproof way should be the one that I used to use when using Oracle.It was a method that took two strings, date representation and format, and returned the date "object". The conversion from date to string could also be done using an explicit format. In python we could of course use a default argument for the explicit format. Hannu Krosing _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From mwm@contessa.phone.net Tue Dec 9 17:31:32 1997 From: mwm@contessa.phone.net (Mike Meyer) Date: Tue, 9 Dec 1997 09:31:32 PST Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) In-Reply-To: <348D3A14.4684AAD9@uni-duesseldorf.de> Message-ID: <19971209.76E6AA0.8C4B@contessa.phone.net> > Right now, I'm curious what you think about the time handling. > We are bound to stumble into daylight savings time here + time zones > which both are hard to handle. While the time zone can be deduced > from time.timezone, the DST can only be guessed at. Actually, the DST information is available on most Unix systems, derivable from the time & timezone information. The code for doing this is publicly available, and fairly easy to port to things that aren't Unix. One would hope that the C library routines used by the Python time module used them, and the compiler vendors did the port (or an emulation). > There are basically two options: > > 1. use GM time (AKA Zulu time AKA UTC) as internal basis > and have some external method deduce the DST & time zone > 2. store whatever the user gives to the object and return > it in the same way The longer I look at this, the more confused I get. Could you provide more details about what you're contemplating? I know what I think it should do, but... Thanx, References: <348543B6.9A72B97@uni-duesseldorf.de> <34857793.5C072B43@sid.trust.ee> Message-ID: <199712091838.NAA32299@fermi.eeel.nist.gov> Hannu Krosing writes: > M.-A. Lemburg wrote: > can't we still have _one_ dbi module, that the db modules also use so that > we can still do the 'is' comparison.this is needed for exceptions anyhow. > > Also, considering the new packaging scheme in 1.5, the db interface might > also be restructured to use the new scheme. > so that it will actually be db.interface or something Here's an example dbi packaging hierarchy that could be used for organizing databases in python. An example __init__.py is attached for the top level. This module has a function that can be used by an end users to selectively load a particular database interface directly into the dbi namespace. This approach has a problem which I think makes it a bad idea. Only one database could be loaded into the dbi namespace in an application. It would not be possible to safely connect to another database in the same manner. This would only be a problem if more than one person tried to use the dbi.use() function in an application. Multiple databases could be opened, but they would have to use fully qualified names to distinguish namespaces. package dbi: dbi |---__init__.py | |---demos | |---__init__.py | | | |---dbtest.py | |---sybase | |---__init__.py | | | |---sybase.so ??? | |---otherdb |---__init__.py ###################### package dbi ######################### #contains one file: __init__.py """function 'use' will try loading a module named in parameter 'db' Names from the module will be injected into the dbi namespace. """ import sys class DB_ERROR: """manage problems with dbi here.""" def __init__(self, message): self.message = message def __repr__(self): return self.message def use(db): if db == "gdbm": print "loading gdbm" import gdbm sys.modules['dbi'].__dict__.update(gdbm.__dict__) return "a" elif db == "sybase": try: print "loading sybase" import sysbase sys.modules['dbi'].__dict__.update(sybase.__dict__) return "sybase" except: raise DB_ERROR, "Sybase not installed properly" ###################### demo script dbtest.py ################## """ demo script that show how to use name injection trick Fir try to open sybase. If sybase isn't available the exception will trigger loading gdbm instead. """ import dbi try: dbi.use("sybase") except: dbi.use("gdbm") print "local namespace should have gdbm names in it:" print " ", dir(dbi) db = dbi.open("/tmp/foo","c") db['y'] = 'r' del db ndb = dbi.open("/tmp/foo","c") print ndb['x'] print ndb['y'] _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Tue Dec 9 20:22:09 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Tue, 09 Dec 1997 21:22:09 +0100 Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) References: <19971209.76E6AA0.8C4B@contessa.phone.net> Message-ID: <348DA871.216750A2@uni-duesseldorf.de> Mike Meyer wrote: > > > Right now, I'm curious what you think about the time handling. > > We are bound to stumble into daylight savings time here + time zones > > which both are hard to handle. While the time zone can be deduced > > from time.timezone, the DST can only be guessed at. > > Actually, the DST information is available on most Unix systems, > derivable from the time & timezone information. The code for doing > this is publicly available, and fairly easy to port to things that > aren't Unix. One would hope that the C library routines used by the > Python time module used them, and the compiler vendors did the port > (or an emulation). I looked at the manpages, but couldn't find any hint as to how to determine start and end of the DST, if not given by the environment variable TZ. Looks like we'd have to probe mktime/ localtime to find out. There's lots of information in the tzfiles, but I haven't (yet) found a usable interface to access it. > > > There are basically two options: > > > > 1. use GM time (AKA Zulu time AKA UTC) as internal basis > > and have some external method deduce the DST & time zone > > 2. store whatever the user gives to the object and return > > it in the same way > > The longer I look at this, the more confused I get. Could you provide > more details about what you're contemplating? I know what I think it > should do, but... If we'd use UTC as internal basis (which is what I am favoring at the moment since the C functions use the same basis for the time_t values), conversion functions/methods are necessary and these are like most locale dependant stuff bound to change now and then. If we leave the semantics of the stored value to the user, nodbody but him/her would know e.g. if the times use DST or not. On the other hand no conversion is necessary at all. Time calculations can result in errors though, if e.g. you compute the difference between a date in summer and a date in winter. A good compromise, IMHO, is to provide an interface for conversion much like the one dates will use. Those who need special things in this respect can then easily code their locale dependant conversion in Python. I'm thinking here of something along the lines of the copy_reg-module with which you can register new pickle handlers. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timehorse@unforgettable.com Tue Dec 9 22:07:01 1997 From: timehorse@unforgettable.com (Jeffrey C. Jacobs) Date: Tue, 9 Dec 1997 17:07:01 -0500 Subject: [DB-SIG] Standardized Date-Time class Message-ID: <01BD04C4.DEFDD480@aceltd0185.aceltd.com> Hi, all! This is my first post to the DB Sig, and I may be a day or so out of = step with the rest of you, but I have been talking with Prof. Reingold, = the author of the Calendar converter written in C mentioned by Christian = Egli yesterday, and he possesses many other calendar converters which he = is not making available to the general public, but would allow to be = distributed freely if for non-commercial use in Python form based on the = original Lisp code. Thus, it would be nice if we do build a Calendar = converter into the Date-Time object, that the converters can be loaded = modularly, so that if a non-commercial entity wishes to use the = Reingold-Dershowitz algorithms, they may just plug them in, but = otherwise they need not be included. In this way, each Calendar could = be loaded optionally, so that if one was only concerned with Gregorian = and ISO, one wouldn't have to load Hebrew, Islamic or Mayan. Grabbing the statements from Jim Fulton mentioned before: > It would be helpful to have a standard date-time implementation for > use in Python database implementations (and elsewhere, of course). > =20 > I think that the date-time implementation should: > =20 > 1. Support conversion from strings in a very wide variety of formats > (e.g. 'Oct, 1, 1994 12:34am EST', '1994/10/1 00:34:21.456') This would be calendar dependent, and thus reside in a given Calendar's = module, however, if I write "1 Juli 1972", "1er Janvier", or "15 Maggio = 44 B.C.", how would those be interpreted? And if I write "97/12/09", as = I would in Japan, will it know what I mean? > 2. Support subtraction of date-times, and addition and=20 > subtraction of dates and numbers. I think the general idea that time is actually two concepts, Time and = TimeSpan, may be the best way of looking at this, and since the way = Times are stored may not necessarily be in Seconds since some standard = Epoch, adding a number to a Time may be confusing: "What am I adding? = Seconds? Milliseconds? Days? Floating point? Integer?" Where as a = TimeSpan class could be created as a co-class of Time, using the same = storage format, and having interfaces which make it clear the span of = time stored in the object. > 3. Store dates efficiently. I would think that Dates and Time being basically one concept, should = be combined into 1 Time class, and given the precision of most computers = purporting to be in milliseconds, a very simple way of storing Dates = would be a long indicating the number of Milliseconds since some epoch. = The Gregorian epoch then would be a logical choice, making it the = default calendar; the number of Milliseconds expired since Monday, 1 = January 1 AD at 00:00:00.000 UTC would certainly be my suggestion. You never know if you want to calculate the time the Earth was created = as Tuesday, 4 November 5,371,840,012 BC at 12:36:14.009 UTC (in a = non-secular context); a floating point will over-flow, though a long = will maintain precision. I know, how often are you going to need to use = the day the Earth was created, but isn't it nice knowing that you *can*? = :) Thus, the TimeSpan would also be a quantity in Milliseconds, though = such an object may be initialized in Days or Seconds, I should think. Of course, if most calculations are done based on Seconds or Days, then = this storage method is not optimal. > 4. Store dates immutably. I may sound stupid with this one, but if the module is written in = python, and not compiled, then theoretically wouldn't you always be able = to change the internal structure of your Time class? Say I write: > foo =3D TimeModule.Time(time.time()) # foo =3D The Current Time > foo.MyInternalTimeStorage =3D 42 > foo.PrintDate() 'January 1, 1 AD 00:00:00.042 UTC' > There may be a way around this in Python, but alas I don't know it. = Thus, the only way I know to achieve true immutability would be to write = the Time and TimeSpan classes in C++ and then compile that to a Python = module. I guess I can leave this issue to someone else who would know = more about this aspect of Python than I. > 5. Represent dates to a specified minimum precision=20 > (e.g. milliseconds). See 3. > 6. Handle all dates in the Gregorian calendar. (e.g. there should > not be problems storing dates from the 18th or 21st centuries.) As I said above, supporting non-Gregorian calendars may be made = optional, but the Gregorian module should be loaded with the TimeModule, = and therefore support of arbitrary Gregorian dates should be feasible. > 7. Provide read-access to date-components (e.g. year, month, second, > day-of-week, etc.) That would also be an aspect of each Calendar module, such as the = default Gregorian type, though given how I have set up the Calendar = definition, each quantity would have to be calculated dynamically. > I'm afraid the implementation should also address issues like: > =20 > 8. Support for time-zones, > > 9. Support for daylight-savings time. Having examined and pilfered the definitions for 51 standard TimeZones = and their corresponding rules for DST, this should be doable as a simple = look-up, with some minor calculations. The C-Library support for DST = that I have is based on these rules and doing a lookup for which is the = local TimeZone using an OS API. Since I think normally the TimeZone is = stored in the environment variable "TZ" as a string of the form = "GMTh[:m[:s]][GDT]", I am lead to believe that if the GDT string is = included, indicating that this TimeZone supports Daylight Savings, then = the offset will always be 1 hour, begins the first Sunday in April at = 02:00:00 and ending the last Sunday in October at 02:00:00. Since this = is not at all valid universally, especially in countries in the southern = hemisphere or outside Europe and North America, storing the DST rules as = well as the name would seem wise. However, given the list of TimeZones that I have, all the names are in = full format, "Greenwich Mean Time", not "GMT", which is what is = reflected in Python when I type "> time.tzname". If some other system = is using the 3-Character form, the lookup will have to be modified so = that that TimeZone can be found in the list of TimeZones. Another issue which may be important is that in the US, the rules for = when DST begins I believe were changed from beginning the last Sunday in = April to the current rules in 1987, so what do we calculate for the Time = in mid April in the US before 1987? Could TimeZones have more than one = set of Daylight Savings rules depending on the year being calculated? What I'm getting at here, is if we are going to support Universal Time = from 5 billion BC to 1 billion AD or what have you, we will have to = replace the C-Library TimeZone routines with something more robust. I'm = currently examining the GNU implementation of TimeZones and I may = elaborate on this in a later post. Just as in interesting aside, one thing I have found is that since Leap = Seconds have been instituted in 1972, there have been 21 occurrences as = of 30 June 1997, thus any times before 1972 will be off by about 21 = seconds. One final and potential To Do, coming full circle on the whole Calendar = concept: since in Hebrew and Islamic calendars the day begins at = Sundown, wouldn't implementation of Sunrise and Sunset calculations make = things more precise, if they could also be included optionally? = Certainly, this would be a very low priority. Anyway, those are my thoughts on Time based on the work I have been = doing so far in Python building my own Time and Calendar modules, which = I will try to post when I work out some structural issues, such as = standardizing the Calendar modules and getting everything to be in = milliseconds. Be Seeing You, Jeffrey. --- ~,-;` The TimeHorse Sometimes also a Dragon. . . _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From mwm@contessa.phone.net Wed Dec 10 00:12:48 1997 From: mwm@contessa.phone.net (Mike Meyer) Date: Tue, 9 Dec 1997 16:12:48 PST Subject: [DB-SIG] Standardized Date-Time class In-Reply-To: <01BD04C4.DEFDD480@aceltd0185.aceltd.com> Message-ID: <19971209.78F4A28.ED46@contessa.phone.net> > > 2. Support subtraction of date-times, and addition and=20 > > I think the general idea that time is actually two concepts, Time and = > TimeSpan, may be the best way of looking at this, and since the way = > Times are stored may not necessarily be in Seconds since some standard = > Epoch It's really only one concept - TimeSpan. A Time is just a TimeSpan since some standard Epoch. Representing the span as a number of seconds is easy and has some obvious advantages, but it has serious disadvantages as well. Since time is easier to type than timespan, I'll use that instead. >, adding a number to a Time may be confusing: "What am I adding? = > Seconds? Milliseconds? Days? Floating point? Integer?" You don't add numbers to a time; you add times to times. Representing times as a numeric quantity of some obvious unit makes it look like you can add numbers, but that's not really the case. However, we want that to be easy, so some function that has optional arguments for various time units and returns a time representing the number specified would be nice. Have to stop with days or weeks, though, as months and years have variable lengths. > > 6. Handle all dates in the Gregorian calendar. (e.g. there should > > not be problems storing dates from the 18th or 21st centuries.) > As I said above, supporting non-Gregorian calendars may be made = > optional, but the Gregorian module should be loaded with the TimeModule, = > and therefore support of arbitrary Gregorian dates should be feasible. Is it going to be Gregorian all the way back, or is it going to convert to Julian at some point in the past? That conversion is recent enough to effect events of historical interest, not having happened until this century in some countries. > > 9. Support for daylight-savings time. > Another issue which may be important is that in the US, the rules for = > when DST begins I believe were changed from beginning the last Sunday in = > April to the current rules in 1987, so what do we calculate for the Time = > in mid April in the US before 1987? Could TimeZones have more than one = > set of Daylight Savings rules depending on the year being calculated? That's not the only time that they were changed in the US. And the US isn't the only place they've changed. > What I'm getting at here, is if we are going to support Universal Time = > from 5 billion BC to 1 billion AD or what have you, we will have to = > replace the C-Library TimeZone routines with something more robust. I'm = > currently examining the GNU implementation of TimeZones and I may = > elaborate on this in a later post. I don't know who's C library routines you're using, but the ones shipped as part of most Unix sytsems are pretty robust. I haven't checked the GNU version, but I suspect that they're based on the code that Sun released to the public in '87, which is what most Unix systems use. These include the ability to externally specify TZ tables that vary from year to year & locale, and manage to capture such oddities as Arizona not doing DST at all, and Hawaii having one day of DST in 1933. > -----Original Message----- > From: M.-A. Lemburg [SMTP:lemburg@uni-duesseldorf.de] > Sent: Tuesday, December 09, 1997 4:31 AM > To: DB-SIG @ Python.org > Subject: Re: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) > > I'll have a (proto-)type for date/time handling ready in a few days. > It uses Christian Egli's absolute date as internal date repesentation > (making it compatible to his module) and seconds since midnight as > time basis. The internal calendar used is the Gregorian, all other > notations/calendars can interface to it via the absolute date which > can easily be extracted from Christian's objects. > This sounds fine, except the time part needs to be more accurate then to the second.. A float as the # of seconds past midnight sounds fine in this regard. That way you can still retain the billionths of a second # that you find in ODBC's TIMESTAMP_STRUCT. I'm sure other database APIs have things that equivalant to this. > Right now, I'm curious what you think about the time handling. > We are bound to stumble into daylight savings time here + time zones > which both are hard to handle. While the time zone can be deduced > from time.timezone, the DST can only be guessed at. > > There are basically two options: > > 1. use GM time (AKA Zulu time AKA UTC) as internal basis > and have some external method deduce the DST & time zone > 2. store whatever the user gives to the object and return > it in the same way > No, there is only 1 option... #2, store whatever the user gives us. It is the user's problem to go about sorting out timezones and DST nonsense. > Conversion from date/time to strings is left to strftime(). The > other way around could be handled by an elaborate module written > in Python (something a la Skip's date.py) -- it's much too messy > to get written in C. > Actually we should supply strptime() in C, esp. since the source is already availible. Easiest way to do that is to snarf the BSD libc functions from say: ftp://ftp.freebsd.org/.25/FreeBSD/FreeBSD-current/src/lib/libc/stdtime and modify as appropriate. Locale stuff can be handled with OS's that support localeconv() We can #ifdef the approriate sections if they haven't already. So all the C date/time module has to do is: 1) Expose the following date/time type methods a) Construction: taking a # of days since Sunday, December 31, 1 BC, and the # of seconds past midnight b) method to return the # of days, or the # of seconds c) a method that returns a struct tm like tuple like localtime() returns d) a method that returns a float where the fraction part is: #secs in a day/#seconds in this instance 2) Expose strptime() that takes a format string, a string to attempt to parse, and returns a struct tm like structure Possibly raising an exception if the string doesn't parse correctly? 3) Method that takes a struct tm like tuple and generates a date/time type. Everything else should live in Python code. The ODBC glue code can thusly call dbi.makeDateTime(#days, #secs) (or whatever the exact name of it is) The DBI module can then call the date/time type's construction function. An interesting question in date/time types which there prolly is no RIGHT answer is: If my datetime type doesn't store month/day/year information should they be cached calculations, or should I calculate them each time? Bill Tutt billtut@microsoft.com Not speaking for Microsoft, etc... _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From billtut@microsoft.com Wed Dec 10 00:57:35 1997 From: billtut@microsoft.com (Bill Tutt) Date: Tue, 9 Dec 1997 16:57:35 -0800 Subject: [DB-SIG] Standardized Date-Time class Message-ID: <4D0A23B3F74DD111ACCD00805F31D810453711@red-msg-50.dns.microsoft.com> > -----Original Message----- > From: mwm@contessa.phone.net [SMTP:mwm@contessa.phone.net] > Sent: Tuesday, December 09, 1997 4:13 PM > To: db-sig@python.org > Subject: Re: [DB-SIG] Standardized Date-Time class > > > I don't know who's C library routines you're using, but the ones > shipped as part of most Unix sytsems are pretty robust. I haven't > checked the GNU version, but I suspect that they're based on the code > that Sun released to the public in '87, which is what most Unix > systems use. These include the ability to externally specify TZ tables > that vary from year to year & locale, and manage to capture such > oddities as Arizona not doing DST at all, and Hawaii having one day of > DST in 1933. > > That's not the only odd things happening... For a good laugh read your closest zoneinfo source files... People have done really bizzare things with timezones. Bill _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timelord@user2.mnsinc.com Wed Dec 10 06:30:47 1997 From: timelord@user2.mnsinc.com (Jeffrey Jacobs) Date: Wed, 10 Dec 1997 01:30:47 -0500 (EST) Subject: [DB-SIG] Standardized Date-Time class In-Reply-To: <19971209.78F4A28.ED46@contessa.phone.net> Message-ID: On Tue, 9 Dec 1997, Mike Meyer wrote: > > > 2. Support subtraction of date-times, and addition and=20 > > > > I think the general idea that time is actually two concepts, Time and = > > TimeSpan, may be the best way of looking at this, and since the way = > > Times are stored may not necessarily be in Seconds since some standard = > > Epoch > > It's really only one concept - TimeSpan. A Time is just a TimeSpan > since some standard Epoch. Representing the span as a number of > seconds is easy and has some obvious advantages, but it has serious > disadvantages as well. Since time is easier to type than timespan, > I'll use that instead. Well, if we do store time as really a TimeSpan from some epoch, then I can see your point, but from an interface point of view (and remembering that storing an absolute time as such a TimeSpan offset is only a suggestion for internal storage, and wouldn't necessarily have to be the case), there is a strong difference between 61,292,782,211,360 milliseconds and Wednesday, 10 December 1997 4:50:11.360 UTC, or even 11 O'Clock and 11 Hours. What does it mean to add 1 January to 7 September? Although as a general rule, times very close to 0 will probably be TimeSpans, if I have that value stored and then forget what my variable actually represents, my program could end up telling me it's Monday 1 January 1 AD 00:01:45.000 UTC. Although a good programmer will not make that mistake, it's nice knowing that the structure of the language won't let you make the mistake anyway. Thus, I really do feel a strong proponent of the separation of time and span. > > > 6. Handle all dates in the Gregorian calendar. (e.g. there should > > > not be problems storing dates from the 18th or 21st centuries.) > > As I said above, supporting non-Gregorian calendars may be made = > > optional, but the Gregorian module should be loaded with the TimeModule, = > > and therefore support of arbitrary Gregorian dates should be feasible. > > Is it going to be Gregorian all the way back, or is it going to > convert to Julian at some point in the past? That conversion is recent > enough to effect events of historical interest, not having happened > until this century in some countries. I have thought about this, and think that the only complete solution to this problem is to create an Historical Calendar, which does not include the 10 days from 5 to 15 October in 15?? when Pope Gregory changed the calendar from the Julian model, and would use the Julian model for dates before then. However, as this makes things rather complicated, and internally I would still suggest storing Time as a TimeSpan relative to a *projected* Gregorian epoch, as if the Gregorian Calendar had been used from 1 January 1 AD, support for pre-Gregorian dates would not be built into the default Gregorian module. However, since one could simply load the Julian calendar and input a date using that interface, which would then internally store it in the Gregorian TimeSpan form, the problem becomes one of knowing what is the calendar you are inputting, which I think in most cases will be known. Another problem with the idea of a Historical Calendar module is that around 8 BC, due to problems with the Roman Government not keeping proper track of the leap years, Caesar Augusta decreed that the years 8 BC to 8 AD should not be leap years. Thus, Calculating 29 February 4 AD, although valid in the Julian and Gregorian calendar modules, would be historically non-existent. And certainly the Romans were measuring their years in years since the founding of Rome, not in years before the approximate birth of Christ. (How would they know?) > > > 9. Support for daylight-savings time. > > Another issue which may be important is that in the US, the rules for = > > when DST begins I believe were changed from beginning the last Sunday in = > > April to the current rules in 1987, so what do we calculate for the Time = > > in mid April in the US before 1987? Could TimeZones have more than one = > > set of Daylight Savings rules depending on the year being calculated? > > That's not the only time that they were changed in the US. And the US > isn't the only place they've changed. Agreed. This is a can of worms, and I wouldn't suggest supporting retro-fitted DST for every single region of the world. Projecting the current rules to any year, future or past should be the priority. Worrying about how governments have changed how they calculate DST should be secondary. > > What I'm getting at here, is if we are going to support Universal Time = > > from 5 billion BC to 1 billion AD or what have you, we will have to = > > replace the C-Library TimeZone routines with something more robust. I'm = > > currently examining the GNU implementation of TimeZones and I may = > > elaborate on this in a later post. > > I don't know who's C library routines you're using, but the ones > shipped as part of most Unix sytsems are pretty robust. I haven't > checked the GNU version, but I suspect that they're based on the code > that Sun released to the public in '87, which is what most Unix > systems use. These include the ability to externally specify TZ tables > that vary from year to year & locale, and manage to capture such > oddities as Arizona not doing DST at all, and Hawaii having one day of > DST in 1933. Yes. The first implementation I examined was a commercial implementation from a certain omnipresent software entity that will hopefully get it's but kicked by the US Federal Government, but that's another story. I have been able to examine the GNU implementation of tzset(), and realize that the full interpretation of the TZ environment variable is more complicated than is implemented in the first version I studied. Basically, TZ has the following form: sss[+/-][hh[:mm[:ss]]][lll[+/-][hh[:mm[:ss]]][{d,Jd,Mm.w.d}[/hh[:mm[:ss]]]][,[{d,Jd,Mm.w.d}[/hh[:mm[:ss]]]]]] {Phew!} Where, sss = The 3-character abbreviation for the local Time Zone, hh = hour mm = minute ss = second The first [+/-][hh[:mm[:ss]]] is the offset from UTC for this Time Zone. If the sign is excluded, it is assumed to be negative, i.e. American Time. lll = The 3-character abbreviation for the Daylight Savings Time. If lll is not present, this Time Zone has no Daylight Savings time. This is followed by the offset from UTC for the DST of this Time Zone, which is the Standard Time offset + 1 hour if it is not present. This is optionally followed by the beginning and ending times of Daylight Savings Time, respectively. The first argument of the DST dates is in one of three formats: d -- The number of days since 1 January of this year (1 January = 0) Jd -- The Julian date: 1 January = J1, and 29 February = J59, regardless of leap year. Thus J60 always represents 1 March, and to calculate the offset from 1 January, one must subtract 1 from Jd in Leap years and before 1 March, and subtract 2 in standard years from 1 March on. Mm.w.d -- The week of the change over: m is the month, w is the week (1 = first, 4 = fourth, 5 = last), and d is the day of the week (0 = Sunday), thus M4.1.0 would be the first Sunday in April, the default value for the beginning of DST if none is given. The last Sunday in October (M10.5.0) is the default for the last day of DST. Finally, following the day specification is the time of day of the change over, in the same format as the bias. This defaults to 2 am in both dates. Thus, it should be possible to calculate the local DST using the information in the TZ environment variable, if it exists, though it will probably not on most Windows systems, as these tend to rely on the Win32 APIs. Also, converting from local time to some other Time Zone should be supported, and thus a database of known Time Zones would be a nice feature of the new Time module, supporting both the 3-character Time Zone names as well as the full-names, of which I have a list of 51 standard Time Zone settings, as I mentioned before. Be Seeing You, Jeffrey. _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From mwm@contessa.phone.net Wed Dec 10 08:14:46 1997 From: mwm@contessa.phone.net (Mike Meyer) Date: Wed, 10 Dec 1997 00:14:46 PST Subject: [DB-SIG] Standardized Date-Time class In-Reply-To: Message-ID: <19971210.7D4EF70.C6C@contessa.phone.net> > From: Jeffrey Jacobs > be the case), there is a strong difference between 61,292,782,211,360 > milliseconds and Wednesday, 10 December 1997 4:50:11.360 UTC, Yeah - they are radically different presenatations of what I presume is the same object. One presentation makes the implicit reference point explicit. > or even 11 O'Clock and 11 Hours or 6 bells for that matter. I'd say '11 hundred hours" for the latter, but that's really confusing. > What does it mean to add 1 January to 7 September? Since neither has any meaning as stated, nothing. > Although as a general rule, times very close to 0 will probably be > TimeSpans, if I have that value stored and then forget what my variable > actually represents, my program could end up telling me it's Monday 1 > January 1 AD 00:01:45.000 UTC. This is a standard problem > Although a good programmer will not make > that mistake, it's nice knowing that the structure of the language won't > let you make the mistake anyway. Thus, I really do feel a strong > proponent of the separation of time and span. I don't know any programmers that good. However, it's not the structure of the language, it's the structure of the objects. Since we're not implementing them, it isn't really up to us. Code speaks louder than logic. > I have thought about this, and think that the only complete > solution to this problem is to create an Historical Calendar, which does > not include the 10 days from 5 to 15 October in 15?? when Pope Gregory > changed the calendar from the Julian model, and would use the Julian model > for dates before then. That's not complete. The box I'm sitting at recognizes the change as per the US (because I lifted the code from Unix), which was 11 days in September of 1752. The change was recognzied (and recorded) by various civil authorities as late as this century. > Another problem with the idea of a Historical Calendar module is > that around 8 BC, due to problems with the Roman Government not keeping > proper track of the leap years, Caesar Augusta decreed that the years 8 BC > to 8 AD should not be leap years. Thus, Calculating 29 February 4 AD, > although valid in the Julian and Gregorian calendar modules, would be > historically non-existent. And certainly the Romans were measuring their > years in years since the founding of Rome, not in years before the > approximate birth of Christ. (How would they know?) Sigh. And what about the standard tale of July & August getting extra days for political reasons? > > That's not the only time that they were changed in the US. And the US > > isn't the only place they've changed. > Agreed. This is a can of worms, and I wouldn't suggest > supporting retro-fitted DST for every single region of the world. That's why I suggested using the existing, available code, which covers a large chunk of that. > Yes. The first implementation I examined was a commercial > implementation from a certain omnipresent software entity that will > hopefully get it's but kicked by the US Federal Government, but that's > another story. I have been able to examine the GNU implementation of > tzset(), and realize that the full interpretation of the TZ environment > variable is more complicated than is implemented in the first version I > studied. Basically, TZ has the following form: > > sss[+/-][hh[:mm[:ss]]][lll[+/-][hh[:mm[:ss]]][{d,Jd,Mm.w.d}[/hh[:mm[:ss]]]][,[{d,Jd,Mm.w.d}[/hh[:mm[:ss]]]]]] > > {Phew!} That's the GNU code. The code I'm referring to has a much simpler use for TZ, and is much more flexible that this. You can use it to get the retrofit DST for the past, and change that without changing a line of your code - because it's all table driven. I suspect there are a lot more than 51 timezones, but it's hard to tell. From the looks of things, there are 101 different DST rules in the Americas, but I'm trying to compare binary data files at this point. Message-ID: <348E5F6B.34906543@sid.trust.ee> Mike Meyer wrote: > >, adding a number to a Time may be confusing: "What am I adding? = > > Seconds? Milliseconds? Days? Floating point? Integer?" > > You don't add numbers to a time; you add times to times. Representing > times as a numeric quantity of some obvious unit makes it look like > you can add numbers, but that's not really the case. However, we want > that to be easy, so some function that has optional arguments for > various time units and returns a time representing the number > specified would be nice. Have to stop with days or weeks, though, as > months and years have variable lengths. If it were so easy If you calculate loan interest for a loan with annual interest of 12 percent, using the 30/360 or 30/365 day year then the difference between jan.31 and mar.31 is 60 days , when under some other circumstances it can be something completely different. > > > 6. Handle all dates in the Gregorian calendar. (e.g. there should > > > not be problems storing dates from the 18th or 21st centuries.) > > As I said above, supporting non-Gregorian calendars may be made = > > optional, but the Gregorian module should be loaded with the TimeModule, = > > and therefore support of arbitrary Gregorian dates should be feasible. > > Is it going to be Gregorian all the way back, or is it going to > convert to Julian at some point in the past? That conversion is recent > enough to effect events of historical interest, not having happened > until this century in some countries. Are'nt the two actually the same until the Gregorian split? Hannu Krosing _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From magnus.lycka@tripnet.se Tue Dec 9 23:14:34 1997 From: magnus.lycka@tripnet.se (Magnus Lycka) Date: Wed, 10 Dec 1997 00:14:34 +0100 Subject: [DB-SIG] Standardized Date-Time class In-Reply-To: <01BD04C4.DEFDD480@aceltd0185.aceltd.com> Message-ID: <3.0.1.32.19971210001434.007cca30@mail1.tripnet.se> At 17:07 1997-12-09 -0500, Jeffrey C. Jacobs wrote: > Hi, all! > > This is my first post to the DB Sig, and I may be a day or so out of step with the rest of you, but I have been talking with Prof. Reingold, the author of the Calendar converter written in C mentioned by Christian Egli yesterday, and he possesses many other calendar converters which he is not making available to the general public, but would allow to be distributed freely if for non-commercial use in Python form based on the original Lisp code. >From my point of view they are worthless if I can't use them commercially. I need the revenue from my programming to pay my rent and food. I suggest we forget the professor and reinvent the wheel, if the old wheel won't be allowed to roll freely... Magnus -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From hannu@trust.ee Wed Dec 10 12:10:12 1997 From: hannu@trust.ee (Hannu Krosing) Date: Wed, 10 Dec 1997 14:10:12 +0200 Subject: [DB-SIG] Standardized Date-Time class References: <3.0.1.32.19971210001434.007cca30@mail1.tripnet.se> Message-ID: <348E86A4.C87442BC@sid.trust.ee> Magnus Lycka wrote: > >but would allow to be distributed > >freely if for non-commercial use in Python form based on the original Lisp > >code. > > From my point of view they are worthless if I can't use them commercially. > I need the revenue from my programming to pay my rent and food. I suggest > we forget the professor and reinvent the wheel, if the old wheel won't be > allowed to roll freely... Correct, But unless they come with a license that prohibits any and all commercial programming after looking at them ;), we may use them to get some good ideas for our own date class. Hannu _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From billtut@microsoft.com Wed Dec 10 13:12:31 1997 From: billtut@microsoft.com (Bill Tutt) Date: Wed, 10 Dec 1997 05:12:31 -0800 Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) Message-ID: <4D0A23B3F74DD111ACCD00805F31D810453714@red-msg-50.dns.microsoft.com> > -----Original Message----- > From: M.-A. Lemburg [SMTP:lemburg@uni-duesseldorf.de] > > > > There are basically two options: > > > > > > 1. use GM time (AKA Zulu time AKA UTC) as internal basis > > > and have some external method deduce the DST & time zone > > > 2. store whatever the user gives to the object and return > > > it in the same way > > > > > No, there is only 1 option... > > #2, store whatever the user gives us. It is the user's problem to go > about > > sorting out timezones and DST nonsense. > > Hmm, note that option #1 can emulate option #2 if handled > properly (ie. the conversion routines work right). #1 has the > advantage of also allowing proper time calculations, which > certainly have a use in other contexts apart from DB interfacing > too. > No, not really... people are much better off dealing with this themselves or having an abstraction layer on top of the date/time type deal with this. The job of this date/time type is to be as simple as possible, and certainly not complicated... One may suggest and hint that people should always store date/times as UTC Time/Timezone, but one shouldn't present default conversions for these things. In fact, AFAIK most RDBMSs store datetimes blindly. We should do the same. A sane Python based date arithmetic package will be able to do the same thing and be very clear whats happening. > Local times without DST won't have to use the C routines. > UTC will also always work. The only thing to watch out > here are leap seconds when calculating time differences > in seconds. > The date/time module won't be calculating time differences... Thats somebody elses job.. > > > Conversion from date/time to strings is left to strftime(). The > > > other way around could be handled by an elaborate module written > > > in Python (something a la Skip's date.py) -- it's much too messy > > > to get written in C. > > > > > Actually we should supply strptime() in C, esp. since the source is > already > > availible. > > Easiest way to do that is to snarf the BSD libc functions from say: > > ftp://ftp.freebsd.org/.25/FreeBSD/FreeBSD-current/src/lib/libc/stdtime > > and modify as appropriate. > > Locale stuff can be handled with OS's that support localeconv() > > We can #ifdef the approriate sections if they haven't already. > > That's a new one right ? I've never heard of it until now. > My manpage says: > > This function is only available in libraries newer than > libc version 4.6.5 > > I guess we could provide a version of our own here too. > You're correct it is very new on UNIX boxes.. we should supply our own. Using the BSD version is suggested because of copyright & reuse issues. > > > > So all the C date/time module has to do is: > > 1) Expose the following date/time type methods > > a) Construction: taking a # of days since Sunday, December 31, > 1 > > BC > > and the # of seconds past midnight > > b) method to return the # of days, or the # of seconds > > c) a method that returns a struct tm like tuple like > localtime() > > returns > > Make that gmtime(). BTW: the tuple doesn't have a field for > microseconds. Should we simply make the second entry a float to > also hold the fraction part ? > Err. yeah thats what I meant. (The important part being that the DST field MUST be 0, a -1 or a 1 WILL NOT be allowed.) > I'm already working on this -- it'll also have methods/variables > for day-of-week, day-of-year, year-offset (# days between 31.12.-1 and > 1.1. > of the represented year), flag is-leapyear and maybe one or two > more. Everything is assumed to be UTC and Gregorian. It is the users > responsibility to pass appropriate values (this can be misused to > implement option #2 above). > There isn't a need to assume UTC, let other code assume that.. We do need to assume Gregorian for converting into/outof our type though. We don't need to do the leap year caclulation though... The rest of the information should probably be cached me thinks... > > d) a method that returns a float where the fraction part is: > #secs > > in a day/#seconds in this instance > > That's the OLE date right ? I'll add that too. > You got it.. I can toss you code for converting from the double -> TIMESTAMP_STRUCT and struct tm -> double based off of MFC's routines that do similar things.] > > 2) Expose strptime() that takes a format string, a string to attempt to > > parse, and returns a struct tm like structure > > Possibly raising an exception if the string doesn't parse correctly? > > Yep. > We should at least exposes the CRT's strftime() for the sake of completeness if not including our own version of that as well.. (That way we can garuntee that things will come out ok for years prior to 1900) > > 3) Method that takes a struct tm like tuple and generates a date/time > type. > > I plan to add a function for this. It will take the tuple > as input and return a correctly set date/time instance. > The entries are interpreted as being Gregorian dates and UTC time. > No, no, no, bad, bad, bad.... :) Let other bits of code worry about this timezone nonsense... > > > > Everything else should live in Python code. > > Agreed. > > > The ODBC glue code can thusly call dbi.makeDateTime(#days, #secs) (or > > whatever the exact name of it is) > > The DBI module can then call the date/time type's construction function. > > Right and on output (cursor.execute) it will return instances > of the date/time-type. The user can then stick these into > calendar classes of his/her choice to have them converted > to their timezone or special format. > Yeppers > > An interesting question in date/time types which there prolly is no > RIGHT > > answer is: > > If my datetime type doesn't store month/day/year information should they > be > > cached calculations, or should I calculate > > them each time? > > Hmm, the date/time-types are immutable, so caching the output > from 1.c) is possible. If think I could also expose the > tuple as instance variables: day, month, etc. > > Could someone point me to a URL where I can find the already > inserted leap seconds ? > I'll forward you those 2 C routines later today after I get some sleep. That should take care of most of those annoying details I think... > Does anyone know if we can make the new type pickleable by > providing the __getinitargs__-method ? I've never done > this, but it should work that way. > cPickle is supposed to have a mechanism for pickling extension types that would probably be fairly easy to accomplish... (Convert the type to a Python tuple containing the # of days, and # of seconds and pickle that, I think) Bill Tutt billtut@microsoft.com Not speaking for Microsoft, etc.. _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From aaron_watters@classic.msn.com Wed Dec 10 14:19:55 1997 From: aaron_watters@classic.msn.com (aaron watters) Date: Wed, 10 Dec 97 14:19:55 UT Subject: Date-Time type (was Re: [DB-SIG] DB-API Spec. 1.1a1) Message-ID: Looks like what we need is a standard Date interface for Python, as a numeric type. Actually, probably a suite of them as wrappers to the same base type, ie seconds+1 gives a different (but coercible) result than day+1. I cautiously volunteer to look into this, especially if people can point me to any standards docs or standard treatments of the subject. There's gotta be standards out there. Maybe I'll look to yahoo later. Of course today + 3578 should take leap years into account, etc. First place to look, maybe: calendar.py? -- Aaron Watters _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From jim.fulton@digicool.com Wed Dec 10 16:45:26 1997 From: jim.fulton@digicool.com (Jim Fulton) Date: Wed, 10 Dec 1997 11:45:26 -0500 Subject: [DB-SIG] Date-time types Message-ID: <348EC726.307E@digicool.com> I'm one of those folks who, while interested in the work of this SIG, do not have as much time as they would like to participate. Rather than wading directly into the lengthy discussions on date-time representations, I'll just state a few opinions and make a proposal that is somewhat different from the proposals made here and from statements I made in an earlier discussions. It was nearly a year and a half ago that I made a proposal for a standard Python date-time format. There was significant discussion back then. The discussion ranged over a wide range of topics, much as the current discussion has and the various ideas were so expansive that I gave up trying to formulate a coherent response to them. In retrospect, this was partly my fault, as my initial proposal contained controversial and rather expansive components, like super-generic date-to-string conversion. I have now come to the view that a much simpler approach is needed. I also think it would be inadvisable for us to develop a database date-time specification from scratch when others have already developed reasonable standard specs. Digital Creations has an object-oriented database that we plan, over time, to migrate toward ODMG standard compliance. The ODMG standard specifies a set of date-time data types: - Date, - Time (of day), - TimeStamp (a combination of a date and time), and - Interval I believe that these data types are based on some wider/parallel standards (e.g. SQL x), but I can't provide pointers to the related standard. They are very similar to some structures defined in ODBC. Unfortunately, the ODMG standard does not seem to be available on-line. I will, *within the next 7 days*, type up a Python skeletin (and maybe a complete implementation) for the ODMG data types listed above and share it with this list. I think that when you see these interfaces, you will agree that they provide a reasonable minimal set of functionality that is adequate for data exchange with external systems and to support applications that can build higher-level date-time support. Digital Creations plans eventually to develop and make available both Python- and C-based implementation of the above types to support our database/persistence offerings. We have not decided when to do this, but if you all like these interfaces, then I would accelerate the development schedule. I think that a standard Python date-time type would be a good thing. I think that ultimately, the date-time types should be implemented in C and included in the Python distribution to facilitate data exchange with external systems. Jim -- Jim Fulton mailto:jim@digicool.com Technical Director (888) 344-4332 Python Powered! Digital Creations http://www.digicool.com http://www.python.org _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timehorse@unforgettable.com Wed Dec 10 17:05:52 1997 From: timehorse@unforgettable.com (Jeffrey C. Jacobs) Date: Wed, 10 Dec 1997 12:05:52 -0500 Subject: [DB-SIG] Standardized Date-Time class Message-ID: <01BD0563.FABE5240@aceltd0185.aceltd.com> =09 -----Original Message----- From: Hannu Krosing [SMTP:hannu@trust.ee] Sent: Wednesday, December 10, 1997 4:50 AM To: Jeffrey Jacobs Subject: Re: [DB-SIG] Standardized Date-Time class Otherways we will open yet another can of worms - the leap seconds, = which are applied until this day not by Pure Logic but instead by some universal agreements. --------------- Hannu Krosing Of course, all of the leap seconds have occurred since 1 January 1970, = which is the beginning of the modern computer era, so any times before = that, corrected by 21 seconds, which I believe is the total number of = seconds added since then, would be accurate for any time pre-1970. It's = only in the modern era that we loose second-accuracy because of the Leap = Second. Welcome to the era of the Atomic Clock. :) Be Seeing You, Jeffrey. --- ~,-;` The TimeHorse Sometimes also a Dragon. . . _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Wed Dec 10 23:45:38 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Thu, 11 Dec 1997 00:45:38 +0100 Subject: [DB-SIG] Date-time types References: <348EC726.307E@digicool.com> Message-ID: <348F29A2.28E757B9@uni-duesseldorf.de> Before you all start to code your own version of DateTime(), please wait a few more days and I'll announce the C module I'm working on right now. It includes the basic type for date/time representation and some other wrappers of important functions like strptime() (or maybe a generic one written from the BSD sources as basis). It currently can do this: >>> t = DateTime(729368, 55931.522913) >>> print t # no specific format, just something to look at :-) 15:32:11 12/10/97 UTC >>> t.hour 15 >>> t.minute 32 >>> t.second 11 >>> t.year 1997 >>> t.gmtime() # returns a tuple just like time.gmtime() (1997, 12, 10, 15, 32, 11.522913, 2, 344, 0) >>> t.strftime('%x %X %A') '12/10/97 15:32:11 Wednesday' >>> t.absdate, t.abstime (729368, 55931.522913) >>> import time >>> time.mktime(t.gmtime()) 881764331.0 >>> x = time.mktime(t.gmtime()) >>> time.localtime(x) (1997, 12, 10, 15, 32, 11, 2, 344, 0) >>> o = strptime('12/10/97 15:32:11','%x %X') >>> repr(o) '' >>> o 15:32:11 12/10/97 UTC >>> o = strptime('12/10/997 15:32:11','%x %X') Traceback (innermost last): File "", line 1, in ? DateTime.error: parsing error Plus there is a C API to access these values in a comfortable way too. More methods/funtions will be added as time goes... Note that t.absdate corresponds to the "absolute" date that Christian Egli uses in his classes, so these are usable on top of this basic type. Time calculation can easily be done using the provided values t.absdate and t.abstime by code written in Python. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From mwm@contessa.phone.net Thu Dec 11 03:49:05 1997 From: mwm@contessa.phone.net (Mike Meyer) Date: Wed, 10 Dec 1997 19:49:05 PST Subject: [DB-SIG] Standardized Date-Time class In-Reply-To: <348E5F6B.34906543@sid.trust.ee> Message-ID: <19971210.72E5B40.117D1@contessa.phone.net> > From: Hannu Krosing > If you calculate loan interest for a loan with annual interest of 12 percent, using > the 30/360 or 30/365 day year then the difference between jan.31 and mar.31 is 60 > days , when under some other circumstances it can be something completely different. If you're saying they ignore the passage of actual time in favor of some financial fiction, I think the favor should be returned, and the built-in date/time type should ignore them. Jan 31 + 60 days should be Mar 31. or April 1, depending on whether or not there's a February 29th. Or do we need a "financial" calendar system as well? Hmm - we've got inheritance. Possibly this kind of thing can be done in a subclass? > > > > 6. Handle all dates in the Gregorian calendar. (e.g. there should > > > > not be problems storing dates from the 18th or 21st centuries.) > > > As I said above, supporting non-Gregorian calendars may be made = > > > optional, but the Gregorian module should be loaded with the TimeModule, = > > > and therefore support of arbitrary Gregorian dates should be feasible. > > > > Is it going to be Gregorian all the way back, or is it going to > > convert to Julian at some point in the past? That conversion is recent > > enough to effect events of historical interest, not having happened > > until this century in some countries. > > Are'nt the two actually the same until the Gregorian split? No. Days were added to the calendar to adjust them at the time of the split. So we see George Washington's date of birth reported as "Feb. 22 [Feb. 11, old style], 1732". Further, different countries changed over on different days, from Roman Catholic states in 1582 to Greece in 1932. References: <3.0.1.32.19971210001434.007cca30@mail1.tripnet.se> Message-ID: <3.0.1.32.19971210162029.006b5fd8@mail1.tripnet.se> At 14:10 1997-12-10 +0200, Hannu Krosing wrote: >> From my point of view they are worthless if I can't use them commercially. >> I need the revenue from my programming to pay my rent and food. I suggest >> we forget the professor and reinvent the wheel, if the old wheel won't be >> allowed to roll freely... > >Correct, > >But unless they come with a license that prohibits any and all commercial programming >after looking at them ;), we may use them to get some good ideas for our own date >class. Hm... I think you have to learn to respect copyrights in Estonia if we are to take you in to the European Community. ;-) This is really a tricky legal question, and it's naturally difficult to _catch_ you if you change a reasonable amount of code. Still, if you have seen someone elses code, thought, 'Aha!' and then written your own similar program, it could certainly be argued that your work is derived from the program you saw, and thus a violation. If you never saw the other program that can hardly be claimed. Since it is the source code that is copyrighted it's probably not possible to claim any legal complaints if you only se a program executing and then copy it's function based on percieved behaviour. That's unless you copy a screen layout that is considered to be a work of art I guess... If it's patented, not seeing the original is irrelevant, it's still a violation, but if we are talking about copyrights it is my understanding that 'inspiration' from reading (or watching) someone elses literary work, be it a book, a movie or a source listing, can mean that you end up in a situation where you can suddenly be in a legal jam if you create this thing that you might well have written anyway... Knowledge isn't always beneficial... Magnus P.S. I have no legal education, and regardless of the Berne convention copyright regulations differ between countries, so don't trust me as a legal authority. I just wanted to make you aware that the problem exists. -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From magnus.lycka@tripnet.se Wed Dec 10 16:45:47 1997 From: magnus.lycka@tripnet.se (Magnus Lycka) Date: Wed, 10 Dec 1997 17:45:47 +0100 Subject: [DB-SIG] Standardized Date-Time class In-Reply-To: <19971209.78F4A28.ED46@contessa.phone.net> References: <01BD04C4.DEFDD480@aceltd0185.aceltd.com> Message-ID: <3.0.1.32.19971210174547.006a5afc@mail1.tripnet.se> At 16:12 1997-12-09 PST, Mike Meyer wrote: >You don't add numbers to a time; you add times to times. Representing >times as a numeric quantity of some obvious unit makes it look like >you can add numbers, but that's not really the case. However, we want >that to be easy, so some function that has optional arguments for >various time units and returns a time representing the number >specified would be nice. Have to stop with days or weeks, though, as >months and years have variable lengths. I don't really think I agree with this, and I don't think I'm quite alone either. For instance with Oracle I can type: ('systemdata' just happens to be a table containing one line.) SQL> select sysdate from systemdata; SYSDATE --------- 10-DEC-97 SQL> select sysdate + 5 from systemdata; SYSDATE+5 --------- 15-DEC-97 SQL> select sysdate + sysdate from systemdata; select sysdate + sysdate from systemdata * ERROR at line 1: ORA-00975: date + date not allowed SQL> select sysdate - sysdate from systemdata; SYSDATE-SYSDATE --------------- 0 Certainly, if I have two dates A and B so that: >>> print A, B '1997-04-25' '1997-04-20' Then I want to see: >>> print A - B 5 or perhaps: >>> print A - B '5 days' and certainly not: >>> print A - B '0001-01-05' or whatever five days after epoch might be. >From a theoretical point of view Mike's argument is logical, but I would certainly want an exception raised if someone added A + B where both of these where dates. I could live with A + 5 + 360.0 meaning five days and 6 minutes later than A, but maybe something more like unix at(1) is better. Perhaps A + timespan(5,'d') + timespan(6,'m') or=20 A + timespan('050006','d2h2m2')? I suppose the A + 5 + 360.0 approach=20 might cause problems if it's coerced to A + 365.0. At least=20 'delta =3D 5 + 360.0; A + delta' would be sure to fail. I think that both error checking and string representation issues means that date/time and timespan need to be different things, but when I think of it, it might not be ideal to expose integers and floats as methods for describing time spans. I think I'd like to see time and timespan as two classes, and I guess they could be closely related via inheritance, but the arithmetics should check types. Multiplications with numbers make sense for timespans, for instance 5 * 1 day, but not for times or dates, especially not since there are different time zones. So: class Time/Date: attribute: a date/time, i.e. 1997-12-25 13:45:21.234234234 methods: for setting value (different formats) (__init__) for getting value (different formats)=20 (print using format string and locale default, TZ?) (__repr__? for arithmetic?) __add__ (add with timespan, returns date/time) __sub__ (sub with date/time returns timespan and vice versa) class Timespan: attribute: a timespan, i.e. 5 days, 6 minutes methods: for setting value (different formats) (__init__) for getting value (different formats)=20 (print using format string and locale default, TZ?) (__repr__? for arithmetic?) __add__ (add with timespan,returns timespan add with time/date,returns date/time) __sub__ (sub with timespan returns timespan) __mult__ (sub with float returns timespan) __div__ (sub with float returns timespan) Actually, it could be just one class if that's better for som reasons, but then it should have an attribute keeping track of whether it's relative or absolute (relative to an epoch if you like), so that the control over arithmetic and entry/presentation can be enforced. I.e. class time: attributes: a time/date epoch (Date of epoch??? (seconds since big bang? ;-) or None for relative) methods: __add__ (add the dates unless both have epoch !=3D None.) etc... BTW I suggest time should be immutable, so that it can only be created through the __init__ function. Preferrably we should also include means for adding months and years to dates. It's naturally possibly to add a year to 1997-02-29 or two months to 1998-07-31. We just have to set up rules for how this is to be handled. I guess that should be coded in Python since it might be something people want to be able to modify. For instance, a month could equal 30 days, or it could just be decided that 31 Jan + 1 Mon =3D 28 Feb or 3 Mar. Another issue, should it be possible to add 1.47 months to a date, or just integers for all bus seconds? (Actually, it's the same thing here, all time units up to a week usually have the same length, and don't pose any problems, but what is 15 Dec 1997 + 2.35 months? >Is it going to be Gregorian all the way back, or is it going to >convert to Julian at some point in the past? That conversion is recent >enough to effect events of historical interest, not having happened >until this century in some countries. I suggest that all changes in calendar have to be explicit, but I see no point at all in supporting Julian calendar. Other living calendars than Gregorian could be supported, but that can be fixed in time. The only things that are affected are the methods for printing and entering dates. I guess this can be handled through sub-classing or through making the format handling use some external data file. FYI this is how Oracle handles date formats in TO_CHAR and TO_DATE. It's similar to strftime, but contins a lot more: CC Century SCC Century, BC dates prefixed with '-' YYYY Year SYYYY Year, BC dates prefixed with '-' Y YY YYY Year, last 1,2,3 digits, present millenium/century/decade IYYY 4-digit ISO standard year. (Can be one off to fit week nr) IYY IY I ISO year as above Y,YYY Year with comma in this position SYEAR YEAR Year spelled out RR Last 2 digits of year for years in next century (???) BC AD B.C. A.D. PM P.M. AM A.M. (Guess ;-) Q Quarter of year MM Month 01 - 12 RM Month I to XII MONTH Month JANUARY - DECEMBER MON JAN - DEC WW W Week number of year / month IW ISO std week DDD DD D Day or year,month,week DAY MONDAY etc DY MON etc J Number of days since Dec 31 4713 BC !?? :-) HH (or HH12) Hour of day 1 - 12 HH24 Hour of day 0-23 MI Minutes SS SSSSS Seconds past minute / midnight -/,.;: As is "quoted text" Sligtly shortened SQL session. (Note that ISO year 2000 starts Jan 3rd 2000) SQL> CREATE TABLE x (a DATE, b DATE, c DATE); SQL> INSERT INTO x (a,b,c) VALUES (SYSDATE-750000,SYSDATE+751,SYSDATE+752); SQL> SELECT a,b,c FROM x; 08-JUL-56 31-DEC-99 01-JAN-00 SQL> SELECT TO_CHAR(a,'SCC CC YEAR BC Q MM RM MON MONTH Y IY IW WW W'), 2 TO_CHAR(b,'SCC CC YEAR BC Q MM RM MON Month Y IY IW WW W'), 3 TO_CHAR(c,'SCC CC YEAR BC Q MM RM MON month Y IY IW WW W')=20 4 FROM x; -01 01 FIFTY-SIX BC 3 07 VII JUL JULY 6 56 27 28 2 20 20 NINETEEN NINETY-NINE AD 4 12 XII DEC December 9 99 52 53 5 21 21 TWO THOUSAND AD 1 01 I JAN january 0 99 52 01 1 SQL> SELECT TO_CHAR(a,'D DD DDTH DDSP DDSPTH DDD DY DAY J SYYYY Y'), 2 TO_CHAR(b,'D DD DDTH DDSP DDSPTH DDD DY DAY J SYYYY Y'), 3 TO_CHAR(c,'D DD DDTH DDSP DDSPTH DDD DY DAY J SYYYY Y')=20 4 FROM x; 5 08 08TH EIGHT EIGHTH 190 THU THURSDAY 1700793 -0056 6 6 31 31ST THIRTY-ONE THIRTY-FIRST 365 FRI FRIDAY 2451544 1999 9 7 01 01ST ONE FIRST 001 SAT SATURDAY 2451545 2000 0 SQL> SELECT TO_CHAR(a,'am P.M. HH HH24:MI:SS SSSSS "some text"') 2 FROM x; pm P.M. 04 16:23:55 59035 some text You can also change language to for instance SWEDISH and get something in 'Swenglish'... week days are translated but not numbers. :-( 4 08 08TH EIGHT EIGHTH 190 TOR TORSDAG 1700793 -0056 6 5 31 31ST THIRTY-ONE THIRTY-FIRST 365 FRE FREDAG 2451544 1999 9 6 01 01ST ONE FIRST 001 L=D6R L=D6RDAG 2451545 2000 0 -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Thu Dec 11 11:48:47 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Thu, 11 Dec 1997 12:48:47 +0100 Subject: [DB-SIG] Date-time types References: <4D0A23B3F74DD111ACCD00805F31D81045371C@red-msg-50.dns.microsoft.com> Message-ID: <348FD31F.5BB4A1C8@uni-duesseldorf.de> [busy implementing...] One question: The time module uses 0 as monday, 1 as tuesday,... should the tuple-method of the new type also use this convention, or rather stick to what the C lib does (0=sunday,1=monday,...) which -I think- is ISO standard ? -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From fredrik@pythonware.com Thu Dec 11 12:26:33 1997 From: fredrik@pythonware.com (Fredrik Lundh) Date: Thu, 11 Dec 1997 13:26:33 +0100 Subject: [DB-SIG] Date-time types Message-ID: <01bd0630$040e8820$6fadb4c1@fl-pc.image.ivab.se> >The time module uses 0 as monday, 1 as tuesday,... should >the tuple-method of the new type also use this convention, >or rather stick to what the C lib does (0=3Dsunday,1=3Dmonday,...) >which -I think- is ISO standard ? ISO C, perhaps. Not the date/time representation standard ISO 8601, which say: A week starts with Monday (day 1) and ends with Sunday (day 7). (IMO, rather than letting the week start on a sunday, use Python's standard convention 0=3Dmonday...) And never write date/time code without taking a careful look at ISO 8601 and related ISO standards. The following link might be useful: ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO Cheers /F _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timehorse@unforgettable.com Thu Dec 11 17:16:20 1997 From: timehorse@unforgettable.com (Jeffrey C. Jacobs) Date: Thu, 11 Dec 1997 12:16:20 -0500 Subject: [DB-SIG] Standardized Date-Time class Message-ID: <01BD062E.97872280@aceltd0185.aceltd.com> -----Original Message----- From: Magnus Lycka [SMTP:magnus.lycka@tripnet.se] Sent: Wednesday, December 10, 1997 10:20 AM To: db-sig@python.org Subject: Re: [DB-SIG] Standardized Date-Time class At 14:10 1997-12-10 +0200, Hannu Krosing wrote: >> From my point of view they are worthless if I can't use them = commercially. >> I need the revenue from my programming to pay my rent and food. I = suggest >> we forget the professor and reinvent the wheel, if the old wheel = won't be >> allowed to roll freely... > >Correct, > >But unless they come with a license that prohibits any and all = commercial programming >after looking at them ;), we may use them to get some good ideas for = our own date >class. Hm... I think you have to learn to respect copyrights in Estonia if we are to take you in to the European Community. ;-) This is really a tricky legal question, and it's naturally difficult to _catch_ you if you change a reasonable amount of code. Still, if you=20 have seen someone elses code, thought, 'Aha!' and then written your own similar program, it could certainly be argued that your work is derived from the program you saw, and thus a violation. If you never saw the = other program that can hardly be claimed. Since it is the source code that is copyrighted it's probably not = possible to claim any legal complaints if you only se a program executing and = then copy it's function based on percieved behaviour. That's unless you copy = a=20 screen layout that is considered to be a work of art I guess... If it's patented, not seeing the original is irrelevant, it's still a=20 violation, but if we are talking about copyrights it is my understanding that 'inspiration' from reading (or watching) someone elses literary = work, be it a book, a movie or a source listing, can mean that you end up in a situation where you can suddenly be in a legal jam if you create this=20 thing that you might well have written anyway... Knowledge isn't always=20 beneficial... Magnus P.S. I have no legal education, and regardless of the Berne convention copyright regulations differ between countries, so don't trust me as a legal authority. I just wanted to make you aware that the problem = exists. =20 Those are very good points, and one thing we have to remember is that = many countries, such as China, India and Russia, although in words being = committed to international Copyright law, are often lax in their = enforcement of such laws, so contrary often times they are to the = cultural concept of some of the people of some nations. I will say that on the specific case of the Reingold-Dershowitz = Calendrical algorithms, I am now "dirty", having seen the Lisp source of = the code they are *indending* to patent. Thus, I am pretty forbidden = from writing any Calendar converter and distributing it directly, even = if under the GNU license. As Magnus has implied, having a binary = distribution is different than having the source, however, it is not = perfect. One example you can take from a book I once read about the development = of a microchip which is supposed to emulate some other, rival company = chip. The way the company avoids copyright and patent infringement is = by having an independent entity fully analyze and document the cause and = effect of every possible input on the chip, and then without letting the = analyzers contact in any way the engineers, the engineers proceed to = build a chip which exactly follows the specification defined by the chip = researchers, who themselves have become "dirty" as they have seen the = original chip. Thus in that way, the new chip engineers will have never = seen the rival chip, and thus be "clean" from any potential lawsuit. In software, binary code is sometimes considered clean enough, as the = cost of reverse-engineering the code directly is usually not as great as = developing the code oneself, though this again is a practical point, not = a legal one. And still direct use of the binary form with be a = violation of software license if in a commercial context. Even so, it = is not feasible to distribute any library in only binary form as part of = the Python distribution because of cross-platform support, so rather = than including such code for everyone, it would have to be optional, and = obtained individually on request. Just stepping back to the original point of developing a set Calendar = converters for Python, the code as I understand it that Christian Egli = ported from Reingold-Dershowitz is considered in the public domain, as = the authors are not trying to maintain any hold on the people using it. = It is only for the more complicated Chinese, Mayan and Hindu algorithms, = as well as those for computing Lunar phases and Sunrise/Sunset times = that they have copyrighted and are trying to patent. Note though, that = these algorithms appear at least to some extent in their book, = "Calendrical Calculations", and as my friend has informed me, the patent = office does not allow you to patent what has already been published. = This was the problem with RSA, which in case you haven't noticed has = made its way into Python's Cryptography module, despite the original = authors attempts to prevent its general distribution. However, as I am = directly involved in developing a possible C++ implementation of the = Calendrical algorithms for the authors, I will not be the one to make = any legal test of their material, and I don't think it's worth any of = our time for that. In conclusion, all I suggest is that any Calendar converters we include = in Python be modular and inter-changeable, so that people using Python = commercially can use those in public domain, but need not use the = copyrighted ones, and people wishing to do Calendrical research can = request the full Calendar library set, and simply plug it into python as = if they were part of the standard distribution. Simply, have = Gregorian.pyc, Julian.pyc, Hebrew.pyc, Islam.pyc and ISODate.pyc be part = of the standard distribution, and optionally one can add Hindu1.pyc, = Hindu2.pyc, French.pyc, and Chinese.pyc to their installation and import = them as they do the standard Calendar libraries. Be Seeing You, Jeffrey. --- ~,-;` The TimeHorse Sometimes also a Dragon. . . _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From thomas.marsh@tivoli.com Thu Dec 11 19:01:54 1997 From: thomas.marsh@tivoli.com (Thomas Marsh) Date: Thu, 11 Dec 1997 13:01:54 -0600 Subject: [DB-SIG] Date-time types References: <01bd0630$040e8820$6fadb4c1@fl-pc.image.ivab.se> Message-ID: <349038A2.7B2C275E@tivoli.com> Perhaps there is need to develop a separate internationalization module for this and other region specific domains. This is how Sybase manages this issue and it would be an excellent core python module. Regardless of what standard there is, an order by clause will use whatever date ordering the database implements, of course. Lacking an i18n module, I would have to agree that the date time type should conform as much as possible to the time module in this respect (0=monday). (I'm jumping in on this discussion a little late I'm afraid.) --thomas Fredrik Lundh wrote: > > >The time module uses 0 as monday, 1 as tuesday,... should > >the tuple-method of the new type also use this convention, > >or rather stick to what the C lib does (0=sunday,1=monday,...) > >which -I think- is ISO standard ? > > ISO C, perhaps. Not the date/time representation standard > ISO 8601, which say: > > A week starts with Monday (day 1) and ends with Sunday (day 7). > > (IMO, rather than letting the week start on a sunday, use Python's > standard convention 0=monday...) > > And never write date/time code without taking a careful look at ISO 8601 > and related ISO standards. The following link might be useful: > > ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO -- Thomas Marsh thomas.marsh@tivoli.com Tivoli Systems, Inc. (512) 436 8643 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From magnus.lycka@tripnet.se Thu Dec 11 19:14:28 1997 From: magnus.lycka@tripnet.se (Magnus Lycka) Date: Thu, 11 Dec 1997 20:14:28 +0100 Subject: [DB-SIG] Standardized Date-Time class In-Reply-To: <01BD062E.97872280@aceltd0185.aceltd.com> Message-ID: <3.0.1.32.19971211201428.00747960@mail1.tripnet.se> At 12:16 1997-12-11 -0500, Jeffrey C. Jacobs wrote: > I will say that on the specific case of the Reingold-Dershowitz >Calendrical algorithms, I am now "dirty", having seen the Lisp source of the >code they are *indending* to patent. Thus, I am pretty forbidden from writing >any Calendar converter and distributing it directly, even if under the GNU >license. As Magnus has implied, having a binary distribution is different than >having the source, however, it is not perfect. If they GET a patent, their patented invention is theirs. Clean room procedures doesn't matter then. A patent gives you exclusive rights to an invention, whether someone else also invents it completely independendly does not matter. I don't think you can patent source code though, any more than you can patent blue prints. As far as I understand the patent must refer to an invention. For instance the algorithms for calculating these calendars can be considered inventions, but since they have been used for hundreds of years it might be tricky to patent them... I'm no patent lawyer as I said, but it's really a bit weird if patents are allowed that are just a matter of making some well know and used system structured. As I haven't seen their algorithms I don't really know what I'm talking about here. I must assume that it really is an invention of some sort. I guess you can write any calendar converter you like as long as you don't use their algorithm, as long as you haven't made some kind of agreement regarding this. > One example you can take from a book I once read about the development of >a microchip which is supposed to emulate some other, rival company chip. The >way the company avoids copyright and patent infringement is by having an >independent entity fully analyze and document the cause and effect of every >possible input on the chip, and then without letting the analyzers contact in >any way the engineers, the engineers proceed to build a chip which exactly >follows the specification defined by the chip researchers, who themselves have >become "dirty" as they have seen the original chip. Thus in that way, the new >chip engineers will have never seen the rival chip, and thus be "clean" from any >potential lawsuit. Copyright: yes, patent: perhaps not. If they just 'happen' to come up with the same solution as the chip they copied from, it's still a patent infringement. It is AFAIK perfectly legal to analyze the current patents when you develop something similar to a patented product. In fact, you ought to do this to make sure you don't violate some patent. Patent searches is stantard procedure in large companies as I understand it. Actually, some (japanese) companies are very good at analyzing patents to see how you can apply for patents that are related to an interesting patent from a competitor. For instance if you have the patent on boiling eggs, I make all sorts of patents on using boiled eggs, and then your patent is worthless unless you buy licences for my patents. :-) > Just stepping back to the original point of developing a set Calendar >converters for Python, the code as I understand it that Christian Egli ported >from Reingold-Dershowitz is considered in the public domain, as the authors are >not trying to maintain any hold on the people using it. It is only for the more Copyrights apply by default. Formally it might even be considered a copyright violation that I quote you right now. In this particular case I think I could claim that it's obvious that you permit people in this discussion group to quote you in their replies, but that code is made available does NOT put it in the public domain. It gets into the public domain when the copyright lapses due to old age. (75 years after authors death?) You are on thin ice as soon as you use code written by someone else unless you have an agreement that you might use it, such as a BSD, GPL etc licence. I haven't read the copyright notice on these programs, but if nothing is said about public use, it's not in the publlic domain. (Formally at least.) On the other hand (this might well vary from country to country) I think there are general legal rules saying that if you are aware that something happens and don't do anything about it for a long time you have basically agreed to it and loose your claims. >In conclusion, all I suggest is that any Calendar converters we include in >Python be modular and inter-changeable, so that people using Python commercially >can use those in public domain, but need not use the copyrighted ones, and >people wishing to do Calendrical research can request the full Calendar library >set, and simply plug it into python as if they were part of the standard >distribution. Simply, have Gregorian.pyc, Julian.pyc, Hebrew.pyc, Islam.pyc and >ISODate.pyc be part of the standard distribution, and optionally one can add >Hindu1.pyc, Hindu2.pyc, French.pyc, and Chinese.pyc to their installation and >import them as they do the standard Calendar libraries. Agreed. I'll shut up about patents and copyrights now. Sorry to deviate, but (unfortunately) it's something that we all need to be aware of... Magnus -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Thu Dec 11 17:08:29 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Thu, 11 Dec 1997 18:08:29 +0100 Subject: [DB-SIG] Date-time types References: <01bd0630$040e8820$6fadb4c1@fl-pc.image.ivab.se> Message-ID: <34901E0D.6246E50E@uni-duesseldorf.de> Fredrik Lundh wrote: > > >The time module uses 0 as monday, 1 as tuesday,... should > >the tuple-method of the new type also use this convention, > >or rather stick to what the C lib does (0=sunday,1=monday,...) > >which -I think- is ISO standard ? > > ISO C, perhaps. Not the date/time representation standard > ISO 8601, which say: > > A week starts with Monday (day 1) and ends with Sunday (day 7). > > (IMO, rather than letting the week start on a sunday, use Python's > standard convention 0=monday...) > > And never write date/time code without taking a careful look at ISO 8601 > and related ISO standards. The following link might be useful: > > ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO > Thanks Fredrik. I'll use the Python way then. Those ISO summaries are interesting. Though I doubt any real user will ever want to write: 19930214T131030 for 1993-02-14 13:10:30 or ---14 for the 14. of the current month -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timehorse@unforgettable.com Thu Dec 11 20:54:13 1997 From: timehorse@unforgettable.com (Jeffrey C. Jacobs) Date: Thu, 11 Dec 1997 15:54:13 -0500 Subject: [DB-SIG] Standardized Date-Time class Message-ID: <01BD064D.0BC15530@aceltd0185.aceltd.com> Just to clarify, As I've said at least 3 times, I have been in contact with one of the = authors of the Reingold-Dershowitz algorithms, and have already been = given authorization to produce both a C++ and Python port to their code. = I have studied copyright and patent law and am aware of what may and = may not be done with the code, and as long as it is distributed under = the proper license, the authors do not have any problems with its use. = The just need to keep track of who's using it and for what purpose, and = if you're making money off of it, they want to share in the wealth. Be Seeing You, Jeffrey. --- ~,-;` The TimeHorse Sometimes also a Dragon. . . _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From billtut@microsoft.com Thu Dec 11 22:01:44 1997 From: billtut@microsoft.com (Bill Tutt) Date: Thu, 11 Dec 1997 14:01:44 -0800 Subject: [DB-SIG] Date-time types Message-ID: <4D0A23B3F74DD111ACCD00805F31D81045371F@red-msg-50.dns.microsoft.com> > -----Original Message----- > From: M.-A. Lemburg [SMTP:lemburg@uni-duesseldorf.de] > Sent: Thursday, December 11, 1997 9:08 AM > To: DB-SIG @ Python.org > Subject: Re: [DB-SIG] Date-time types > > Thanks Fredrik. I'll use the Python way then. Those ISO summaries > are interesting. Though I doubt any real user will ever want to > write: > > 19930214T131030 for 1993-02-14 13:10:30 or > ---14 for the 14. of the current month > Actually, that's not true.. YYYY MM DD HH:MM:SS is a very important way of outputting dates.. Whats so great about it is that it allows you to do a sort based on your string date representation, instead of parsing each date into its consituent parts and then doing your comparison. Bill Tutt Not speaking for Micrsoft, etc... _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From magnus.lycka@tripnet.se Fri Dec 12 12:54:25 1997 From: magnus.lycka@tripnet.se (Magnus Lycka) Date: Fri, 12 Dec 1997 13:54:25 +0100 Subject: [DB-SIG] Standardized Date-Time class In-Reply-To: <01BD064D.0BC15530@aceltd0185.aceltd.com> Message-ID: <3.0.1.32.19971212135425.006ee678@mail1.tripnet.se> At 15:54 1997-12-11 -0500, Jeffrey C. Jacobs wrote: >[snip] The just need to keep track of who's using it and for what purpose, >and if you're making money off of it, they want to share in the wealth. I'm not in general opposed to commercial software (which is what they obviously want their software to be, even if they donate it to non-commercial use), but in a situation like this, where we are considering stuff that ought to go into the Python distribution we certainly don't want anything included that is not in agreement with the Python licence. I'm pretty sure Guido won't allow it anyway. Magnus -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Fri Dec 12 15:05:37 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Fri, 12 Dec 1997 16:05:37 +0100 Subject: [DB-SIG] ANN: DateTime type, version 0.1 Message-ID: <349152C1.1416866A@uni-duesseldorf.de> Now that we have decided on the need for a basic date/time type and more or less settled on what it should be able to do and what not, here it is: http://starship.skyport.net/~lemburg/mxDateTime.html You'll find all information regarding the type, how to download and install it on that page. Future releases will also use that URL. I plan to upload the archive to www.python.org and - if you all agree - update the DB API Spec. 1.1 to make it the standard for date/time value passing in and out of databases. While I am going to support this module, I am counting on you out there to provide classes on top of this type to do all the nifty stuff we've been talking about here lately. Christian Egli's classes should can use the type directly since it uses the same absolute date numbering. Note: the mx-prefix is just for packaging, the module itself is named 'DateTime', just like the data type it provides. If you don't have a strptime() function in your C lib, then you should undefine this (HAVE_STRPTIME in the C file). Guido will include a patch for the configure script in the final that does this check for you. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timehorse@unforgettable.com Fri Dec 12 16:20:21 1997 From: timehorse@unforgettable.com (Jeffrey C. Jacobs) Date: Fri, 12 Dec 1997 11:20:21 -0500 Subject: [DB-SIG] Standardized Date-Time class Message-ID: <01BD06EF.F2EBC510@aceltd0185.aceltd.com> -----Original Message----- From: Magnus Lycka [SMTP:magnus.lycka@tripnet.se] Sent: Friday, December 12, 1997 7:54 AM To: 'The Python DataBase Sig' Subject: RE: [DB-SIG] Standardized Date-Time class I'm not in general opposed to commercial software (which is what they obviously want their software to be, even if they donate it to non-commercial = use), but in a situation like this, where we are considering stuff that ought to = go into the Python distribution we certainly don't want anything included that = is not in agreement with the Python licence. I'm pretty sure Guido won't allow it anyway. [The TimeHorse]---------------------------------------------------- Again, the point I am trying to make is that we should make whatever = public-license calendar libraries we do incorporate be modular enough so = that if other libraries come along, they can just be "plugged in". In = that sense, stuffing all the calendar code for every calendar into a = single module will not work as it does not allow for the convenient = addition of other calendar converters, such as the ones I am talking = about. Be Seeing You, Jeffrey. --- ~,-;` The TimeHorse Sometimes also a Dragon. . . _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timehorse@unforgettable.com Fri Dec 12 17:00:22 1997 From: timehorse@unforgettable.com (Jeffrey C. Jacobs) Date: Fri, 12 Dec 1997 12:00:22 -0500 Subject: [DB-SIG] ANN: DateTime type, version 0.1 Message-ID: <01BD06F5.879B54A0@aceltd0185.aceltd.com> -----Original Message----- From: M.-A. Lemburg [SMTP:lemburg@uni-duesseldorf.de] Sent: Friday, December 12, 1997 10:06 AM To: DB-SIG @ Python.org Subject: [DB-SIG] ANN: DateTime type, version 0.1 Now that we have decided on the need for a basic date/time type and more or less settled on what it should be able to do and what not, here it is: http://starship.skyport.net/~lemburg/mxDateTime.html=20 You'll find all information regarding the type, how to download and install it on that page. Future releases will also use that URL. I plan to upload the archive to www.python.org and - if you all agree - update the DB API Spec. 1.1 to make it the standard for date/time value passing in and out of databases. While I am going to support this module, I am counting on you out there to provide classes on top of this type to do all the nifty stuff we've been talking about here lately. Christian Egli's classes should can use the type directly since it uses the same absolute date numbering. Note: the mx-prefix is just for packaging, the module itself is named 'DateTime', just like the data type it provides. If you don't have a strptime() function in your C lib, then you should undefine this (HAVE_STRPTIME in the C file). Guido will include a patch for the configure script in the final that does this check for you. [The TimeHorse]----------------------- Cool! It looks great, though one thing I might point out is that leap = seconds are calculated as the 60th second of the 23rd hour of the 59th = minute. Thus, there is no 24th hour on leap-second days, only that = extra 60th second. There's a cool picture on the web somewhere which is = taken from the USNO atomic clock during the last Leap Second on 30 June = this year, which shows the 60th second. I know you probably don't agree with me on the suggestion I am going to = make, and this has been discussed quite a bit already and maybe we're = all sick of it, but I still feel a co-class of type TimeSpan would be = good, as it makes the future operations of addition and subtraction a = lot more clear. One suggestion made by Jim Fulton the other day sounds = appealing to me too, which is the idea of a separate Date and Time = class, so that the DateTime constructor can accept the immutable Date = and Time object, as opposed to the Absolute date and time values. Of = course, this is only a semantically point, and doesn't really effect = much, and some may feel it over-complicates things, but certainly there = are circumstances when you may only want to retrieve a date, not a time, = in your Database, and may not want the overhead of the time functions, = and visa-versa. I must admit another problem with my suggestion, which = is that if one applies a TimeZone change to a Time object, what does it = mean if the result spans more than one day? It is possible the time may = end up internally as negative, or greater than 24 hours. Despite these = problems, I still tend to lean more towards the 4-class model, or at = least the 2-class (DateTime and TimeSpan). Okay, I've said my peace and will depart now. I look forward to the = new Database support and am happy that it is now very nearly complete. = Thank you all! Be Seeing You, Jeffrey. --- ~,-;` The TimeHorse Sometimes also a Dragon. . . _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Sat Dec 13 21:40:05 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Sat, 13 Dec 1997 22:40:05 +0100 Subject: [DB-SIG] Re: ANN: DateTime type, version 0.1 References: <349152C1.1416866A@uni-duesseldorf.de> Message-ID: <349300B5.52AFF381@uni-duesseldorf.de> Some questions regarding further developements: 1. I'd like to make the DateTime instances pickleable. Unfortunately the pickle mechanism doesn't include a default method for unknown objects. This means we have to provide ur own pickling routines. A generic method in pickle/cPickle wouldn't be a bad idea either, since all that is needed are ways to deduct the name of the module where the instance's constructor can be found and the constructor's name, ie. if an object provides __module__ and __name__ plus optionally the pickle methods __getinitargs__, __getstate__, __setstate__, there should be no problem having a standard mechanism much like save_inst do the job without having to provide explicit pickle/unpickle routines. 2. Though not needed for DB interfacing, it would be nice to have a way to express deltas in time (e.g. +2 months, -3 seconds, etc.). These objects will hold relative data, so calculating a specific fixed number of seconds/days as internal basis is not possible, because e.g. a month can have 28,29,30 or 31 days. Example: t1 = maketime(1997,12,12) t2 = maketime(1998,2,1) d = DateTimeDelta(month=+2) Possible keywords for the constructor: relative: year,month,day,hour,minute,second - add values to resp. fields absolute difference: absdate - add value to absdate, fractions are added to abstime abstime - add value to abstime, overflow is added to absdate (The two categories mutually exclude each other, e.g. if you use month=+2,day=+2 you can't use absdate=+30) t1 + d will point to 1998,2,12 t2 + d will point to 1998,4,1 Questions: - What is the outcome of maketime(1997,12,31) + d ? Since february doesn't have 31 days the new date is not well defined. I guess an exception should be raised to indicate this. - What should t2 - t1 result in ? There are two options: a) it returns a relative result like DateTimeDelta(year=+1,month=-10, day=-11) b) it returns an absolute difference, DateTimeDelta(absdate=+51) I think arithmetic should always use option b). Option a) could be returned by a special reldifftime() function. - Is there a need for addition of deltas ? - Would having seperate types for the two flavors (relative and absolute) be a better approach. [actually while writing this, I tend to think so]. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Sat Dec 13 17:10:43 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Sat, 13 Dec 1997 18:10:43 +0100 Subject: [DB-SIG] ANN: DateTime type, version 0.1 References: <01BD06F5.879B54A0@aceltd0185.aceltd.com> Message-ID: <3492C193.1755E031@uni-duesseldorf.de> Jeffrey C. Jacobs wrote: > > Cool! It looks great, though one thing I might point out is that leap seconds are calculated as the 60th second of the 23rd hour of the 59th minute. Thus, there is no 24th hour on leap-second days, only that extra 60th second. There's a cool picture on the web somewhere which is taken from the USNO atomic clock during the last Leap Second on 30 June this year, which shows the 60th second. > I know, but the current conversion routines are a little simple minded in this respect, which is why leap seconds turn out as: >>> t = DateTime(729371, 86400) >>> t Sat Dec 13 24:00:00 1997 > Okay, I've said my peace and will depart now. I look forward to the new Database support and am happy that it is now very nearly complete. Thank you all! > Depart ? There's still some work to be done and I'm sure you can help ;-) On the todo list are DateTimeDelta to hold time differences, some Calendars (esp. the Julian) and maybe some routines for doing fuzzy date/time parsing - the strptime() function is a little strict in this respect. Users don't always enter dates/times in the exact predefined way, they insert spaces, tabs, switch order of date and time, or just leave out some parts like the seconds. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From magnus.lycka@tripnet.se Sun Dec 14 00:10:23 1997 From: magnus.lycka@tripnet.se (Magnus Lycka) Date: Sun, 14 Dec 1997 01:10:23 +0100 Subject: [DB-SIG] Re: ANN: DateTime type, version 0.1 In-Reply-To: <349300B5.52AFF381@uni-duesseldorf.de> References: <349152C1.1416866A@uni-duesseldorf.de> Message-ID: <3.0.1.32.19971214011023.007667d0@mail1.tripnet.se> At 22:40 1997-12-13 +0100, M.-A. Lemburg wrote: >t1 = maketime(1997,12,12) >t2 = maketime(1998,2,1) >d = DateTimeDelta(month=+2) As I've written before one could also imagine this being the same class with an attribute indicating if the time is relative or not. Although that might not be a good idea since a absolute time can be expressed as a number relative to epoch, while +2 months are sometimes the same as 2592000 seconds, and sometimes something else... Hm, two classes is probably better, they are after all more different than one having an epoch to relate to, and the other just lacking that reference. >(The two categories mutually exclude each other, e.g. if you use > month=+2,day=+2 you can't use absdate=+30) I'm not sure I follow you here. What's the difference of day=+40 and absdate=+40? Why should absdate be different from day? Why not just add the bigger things first? 1900,1,1 + (year=+20,month=+30, day=+40) => 1922,8,10 You might have a problem with which order you add things anyways, even if 'days' is small, so you have to make up your mind here. >>> t = maketime(1998,2,27) >>> m = DateTimeDelta(month=+1) >>> d = DateTimeDelta(day=+2) >>> t1 = t + m >>> print t1 1998,3,27 >>> print t1 + d 1998,3,29 >>> t2 = t + d >>> print t2 1998,3,1 >>> print t2+m 1998,4,1 So, t + m + d != t + d + m. Not funny, but it's not our fault that the months have different lenghts. The way I see it absdate=+X (if I have understood what you meant by that term) is just the same as (year=0,month=0,day=+X). I think the user can handle year = month = 0 if that's what she wants. >Questions: >- What is the outcome of maketime(1997,12,31) + d ? Since february > doesn't have 31 days the new date is not well defined. I guess > an exception should be raised to indicate this. This is obviously something a lot of people have run into lots of times. Banks, authorities etc. Is there not any standard for handling this? I imagine this is something you want to handle differently in different occasions. Sometimes you will probably want it to be Feb 28, and sometimes Mar 3. This probably depends on whether you are paying or receiving money ;-) if it's an economical system for instance... I guess subclassing with the handling of this in the subclass is acceptable. Another option would be to have some extra attribute in DateTimeDelta for longer or shorter spans. But maybe it's better to have a simpler and cleaner system and subclass to handle such things. BTW, can anyone say something about how much an extra level of subclassing affects performance in Python? Since there is late binding, I imagine an extra level (or several) of subclassing will have a performance cost. Is this significant? (I understand this is not a clear yes/no question, but maybe someone can say something enlightening on that issue.) >- What should t2 - t1 result in ? There are two options: > a) it returns a relative result like DateTimeDelta(year=+1,month=-10, > day=-11) > b) it returns an absolute difference, DateTimeDelta(absdate=+51) > I think arithmetic should always use option b). Option a) could > be returned by a special reldifftime() function. >- Is there a need for addition of deltas ? >- Would having seperate types for the two flavors (relative and > absolute) be a better approach. [actually while writing this, I > tend to think so]. Hm... My thought was initially that for instance >>> t1 = maketime(1997,12,12,12,45,50) >>> t2 = maketime(1997,12,12,09,32,55) >>> diff = t2 - t1 # 11575 seconds would come out like >>> print diff 3 hours 12 minutes 55 seconds rather than 3,13,-5 or 11575. Naturally this fails when we come to months... :-( I suppose b) is the right way to do it. How much energy would it take to move the earth closer to the sun so that the year is reduced to 360 days? That would make things sooo much simpler, and it would finally be a proper use of all those A-bombs! ;-) Magnus -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Sun Dec 14 22:48:36 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Sun, 14 Dec 1997 23:48:36 +0100 Subject: [DB-SIG] Re: ANN: DateTime type, version 0.1 References: <349152C1.1416866A@uni-duesseldorf.de> <3.0.1.32.19971214011023.007667d0@mail1.tripnet.se> <34946226.7142A065@uni-duesseldorf.de> Message-ID: <34946244.4A94F27@uni-duesseldorf.de> Magnus Lycka wrote: > > At 22:40 1997-12-13 +0100, M.-A. Lemburg wrote: > >t1 = maketime(1997,12,12) > >t2 = maketime(1998,2,1) > >d = DateTimeDelta(month=+2) > > As I've written before one could also imagine this being the > same class with an attribute indicating if the time is relative > or not. Although that might not be a good idea since a absolute > time can be expressed as a number relative to epoch, while +2 > months are sometimes the same as 2592000 seconds, and sometimes > something else... Hm, two classes is probably better, they are > after all more different than one having an epoch to relate to, > and the other just lacking that reference. Exactly. > >(The two categories mutually exclude each other, e.g. if you use > > month=+2,day=+2 you can't use absdate=+30) > > I'm not sure I follow you here. What's the difference of day=+40 > and absdate=+40? Why should absdate be different from day? You're right, absdate and date should work in the same way, just as seconds and abstime should. > Why not > just add the bigger things first? 1900,1,1 + (year=+20,month=+30, > day=+40) => 1922,8,10 > You might have a problem with which order you add things anyways, > even if 'days' is small, so you have to make up your mind here. Good point, order should be fixed in that way. The keywords probably make things too complicated, so we could just provide some convenient constructors: - DateTimeDelta(year,month,day,hour,minute,second) [the real thing] - DateDelta(year,month,day) (time part is 0) - TimeDelta(hour,minute,second) (date part is 0) All deltas are then applied from left to right. > Not funny, but it's not our fault that the months have different lenghts. > The way I see it absdate=+X (if I have understood what you meant by that > term) is just the same as (year=0,month=0,day=+X). I think the user can > handle year = month = 0 if that's what she wants. > > >Questions: > >- What is the outcome of maketime(1997,12,31) + d ? Since february > > doesn't have 31 days the new date is not well defined. I guess > > an exception should be raised to indicate this. > > This is obviously something a lot of people have run into lots of > times. Banks, authorities etc. Is there not any standard for handling > this? I imagine this is something you want to handle differently in > different occasions. Sometimes you will probably want it to be Feb 28, > and sometimes Mar 3. This probably depends on whether you are paying or > receiving money ;-) if it's an economical system for instance... I guess > subclassing with the handling of this in the subclass is acceptable. > > Another option would be to have some extra attribute in DateTimeDelta > for longer or shorter spans. But maybe it's better to have a simpler and > cleaner system and subclass to handle such things. Simple and clean is always better :-) > BTW, can anyone say something about how much an extra level of subclassing > affects performance in Python? Since there is late binding, I imagine an > extra level (or several) of subclassing will have a performance cost. Is > this significant? (I understand this is not a clear yes/no question, but > maybe someone can say something enlightening on that issue.) It's no big deal if you don't do too much extensions (calling base class methods in overridden methods). I usually apply the following functions to my classes: def freeze(thisclass): """ Add all known attributes of base classes to thisclass's attribute dictionary - does not overwrite attributes """ dict = thisclass.__dict__ if dict.has_key('__frozen__'): return dict.update(frozen(thisclass)) dict['__frozen__'] = 1 def frozen(classinst): """ Return a dictionary that contains all known attributes of classinst - uses cached versions if available """ dict = {} bases = list(classinst.__bases__) bases.reverse() for c in bases: otherdict = c.__dict__ if not otherdict.has_key('__frozen__'): frozendict = frozen(c) else: frozendict = otherdict dict.update(frozendict) dict.update(classinst.__dict__) return dict Once a class is frozen this way, it won't see any changes in its base classes -- but since I don't use this Python feature (on a regular basis) this doesn't bother me. > >- What should t2 - t1 result in ? There are two options: > > a) it returns a relative result like DateTimeDelta(year=+1,month=-10, > > day=-11) > > b) it returns an absolute difference, DateTimeDelta(absdate=+51) > > I think arithmetic should always use option b). Option a) could > > be returned by a special reldifftime() function. > >- Is there a need for addition of deltas ? > >- Would having seperate types for the two flavors (relative and > > absolute) be a better approach. [actually while writing this, I > > tend to think so]. > > Hm... My thought was initially that for instance > >>> t1 = maketime(1997,12,12,12,45,50) > >>> t2 = maketime(1997,12,12,09,32,55) > >>> diff = t2 - t1 # 11575 seconds > would come out like > >>> print diff > 3 hours 12 minutes 55 seconds > rather than 3,13,-5 or 11575. Naturally this fails when we come to > months... :-( I suppose b) is the right way to do it. Ah yes, I haven't though about that yet: how should deltas be stringified ? strftime() is probably not usable since I don't think it handles negative dates/times. Two other things: While fixing mxODBC to use the new type I stumbled into a dynamic linking problem: it seems that the DateTime type must be statically linked to the interpreter, since all other modules using it must reference the same type object to be able to recognize it. Also, how should TIMEs be treated ? I am currently using a DateTime(1,TIME in seconds) instance, but that prevents calcualtions like: today = maketime(1997,12,13) c.execute("select time from timetable where date=?",(today,)) time = c.fetchone()[0] print today + time [TypeException] Daytime is obviously a relative term, so it should probably also be handled as (positive) DateTimeDelta (not having any date part of course). -- Marc-Andre Lemburg PS: I consider all this as brainstorming, so feel free to comment or propose other ways :-) _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timehorse@unforgettable.com Mon Dec 15 17:02:56 1997 From: timehorse@unforgettable.com (Jeffrey C. Jacobs) Date: Mon, 15 Dec 1997 12:02:56 -0500 Subject: [DB-SIG] Re: ANN: DateTime type, version 0.1 Message-ID: <01BD0951.6668B120@aceltd0185.aceltd.com> -----Original Message----- From: M.-A. Lemburg [SMTP:lemburg@uni-duesseldorf.de] Sent: Saturday, December 13, 1997 4:40 PM To: DB-SIG @ Python.org Subject: [DB-SIG] Re: ANN: DateTime type, version 0.1 Some questions regarding further developements: 2. Though not needed for DB interfacing, it would be nice to have a way to express deltas in time (e.g. +2 months, -3 seconds, etc.). These objects will hold relative data, so calculating a specific fixed number of seconds/days as internal basis is not possible, because e.g. a month can have 28,29,30 or 31 days. Example: t1 =3D maketime(1997,12,12) t2 =3D maketime(1998,2,1) d =3D DateTimeDelta(month=3D+2) Possible keywords for the constructor: relative: year,month,day,hour,minute,second - add values to resp. fields absolute difference: absdate - add value to absdate, fractions are added to abstime abstime - add value to abstime, overflow is added to absdate (The two categories mutually exclude each other, e.g. if you use month=3D+2,day=3D+2 you can't use absdate=3D+30) t1 + d will point to 1998,2,12 t2 + d will point to 1998,4,1 Questions: - What is the outcome of maketime(1997,12,31) + d ? Since february doesn't have 31 days the new date is not well defined. I guess an exception should be raised to indicate this. - What should t2 - t1 result in ? There are two options: a) it returns a relative result like = DateTimeDelta(year=3D+1,month=3D-10, day=3D-11) b) it returns an absolute difference, DateTimeDelta(absdate=3D+51) I think arithmetic should always use option b). Option a) could be returned by a special reldifftime() function. - Is there a need for addition of deltas ?=20 - Would having seperate types for the two flavors (relative and absolute) be a better approach. [actually while writing this, I tend to think so]. --=20 Marc-Andre Lemburg [The TimeHorse] =20 Just to go over some of the Questions raised, as far as Months are = concerned, 31 Jan 1998 + 1 Month =3D 28 Feb 1998 seems at least to me = the most intuitive approach. If I wish to increment the month field, I = certainly do not expect the Day to change. Thus, if 31 Feb 1998 doesn't = exist, try 30 Feb, then 29 Feb and finally 28 Feb, basically reducing to = the last date. Again, problems with commutative and closure arise, as = 31 Jan 1998 + 1 month + 1 month =3D 28 March 1998, but 31 Jan 1998 + 2 = months =3D 31 March 1998. The only way around this I can think of is to = hide the days lost due to the increment in a separate internal and add = them back if the month is change again. Thus: Initially: DaysFromMonthLost =3D 0 Date =3D 31 Jan 1998 Date =3D Date + 1 month: DaysFromMonthLost =3D 3 Date =3D 28 Feb 1998 Date =3D Date + 2 months: DaysFromMonthLost =3D 1 Date =3D 30 Apr 1998 Date =3D Date + 3 months: DaysFromMonthLost =3D 0 Date =3D 31 Jul 1998 Date =3D 31 Jan 1998 DaysFromMonthLost =3D 0 Date =3D 31 Jan 1998 Date =3D Date + ( 31 Days * 6) DaysFromMonthLost =3D 0 Date =3D 5 Aug 1998 Note, this is *not* the same as adding 31 days for each month. In fact, = if the user wants to add 31 days for each month, why not just explicitly = add 31 days? The user can even define a constant, MyMonthLength =3D 31 = days. Also, we have this problem with: Initially: DaysFromMonthLost =3D 0 LeapSecondLost =3D 0 DT =3D 30 Jun 1997, 23:59:60 DT =3D DT + 1 day DaysFromMonthLost =3D 0 LeapSecondLost =3D 1 DT =3D 1 July 1997, 23:59:59 DT =3D DT - 1 day DaysFromMonthLost =3D 0 LeapSecondLost =3D 0 DT =3D 30 Jun 1997, 23:59:60 It seems that month and in the case of the leap second day are the only = fields which due to their inconsistent nature in the Gregorian calendar = will cause problems in "lower" fields, which is the crux of the problem = here. And certainly as soon as the lower field is directly modified, = how does that effect our DaysFromMonthLost and LeapSecondLost values? = For instance: Initially: DaysFromMonthLost =3D 1 Date =3D 30 Jun 1998 Date =3D Date + 1 day ??? DaysFromMonthLost =3D 0 ??? Date =3D 30 Jun 1998 ??? ??? DaysFromMonthLost =3D 1 ??? Date =3D 1 Jul 1998 I lean towards the latter possibility, and the only way to empty our = DaysFromMonthLost and LeapSecondLost value is to apply another Month or = Day addition respectively, which will cause the hidden members = DaysFromMonthLost and LeapSecondLost to diminish under the circumstances = described above. Of course, one can imagine successive 31 May 1998 + 1 = month - 30 days operations=20 increasing DaysFromMonthLost astronomically over successive operations. = Perhaps the simplest case is to clear the hidden values each time a = lower-order time value is changed, and make the change as normal, i.e. = above: ??? DaysFromMonthLost =3D 0 ??? Date =3D 1 Jul 1998 Again, I think the most important issue, apart from avoiding the 31 day = month constant (which since it is already supported in the days field, I = feel is not a good interpretation of the month field), DateTime and = DateTimeDelta math should hold for Commutativity, Associativity and = Closure. Certainly, having these hidden fields allow for these to work = in some circumstances, but clearly not all. As far as the second question raised, I agree with Marc-Andre's comment = that differences should be in absolute dates, but with the option of a = higher-level interpretation. This is an important issue, as if = DateTimeDeltas purely store absdate and abstime, then how does one = initialize such an object to 1 month anyway? Thus, perhaps one needs a = separate type of DateTimeDelta object than the one which is a simple = absdate, abstime pair. DateTimeDelta I think should remain the simple = days, seconds pair, but perhaps support for the 9-tuple time object may = also be necessary. That way, you may also use the week field for a + 1 = week operation. Again, I won't even touch the can of worms you have = with the Mayan or Hebrew calendars, should they be used. :) As for addition of Deltas, I don't think this is such a bear if the = DateTimeDelta is the simple absdate, abstime pair. Thus I weigh in on = supporting this, and certainly my views on a separate DateTime and = DateTimeDelta class are well-known. :) Be Seeing You, Jeffrey. --- ~,-;` The TimeHorse Sometimes also a Dragon. . . _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From magnus.lycka@tripnet.se Tue Dec 16 11:44:46 1997 From: magnus.lycka@tripnet.se (Magnus Lycka) Date: Tue, 16 Dec 1997 12:44:46 +0100 Subject: [DB-SIG] Assuming larger time scope In-Reply-To: <34946244.4A94F27@uni-duesseldorf.de> References: <349152C1.1416866A@uni-duesseldorf.de> <3.0.1.32.19971214011023.007667d0@mail1.tripnet.se> <34946226.7142A065@uni-duesseldorf.de> Message-ID: <3.0.1.32.19971216124446.006aeda0@mail1.tripnet.se> Still brain storming... I have to admit that I haven't read all the source that people have referred to recently. I hope that doesn't make the things I write seem all to stupid. Actually, the further I get into this, the more I feel that this might be something for a subclass, rater than the base class. Assuming the construction maketime(year,month,day,hour,minute,second) we can make some assumptions if not all fields are filled. For instance if hour and minute are filled and the rest is left empty, one might certainly assume that seconds should be 0. What should one assume about the date? The trivil assumption would be to assume that it's todays date. But I'm not sure you should always to that. This can also be drawn further: If day is entered, we assume that this month and year is what we are looking for and so on. For this to be logical the same should be assumed for the digits in the year (even though theys are in one variable) since the individual digits are positional items in another way than the two digits in for instance month is. We do write 97 for 1997, but never 2 for december, or 5 for the 25th day of the month. Naturally, this makes us think of the approaching millenium shift. If we write year = 00 today, it's unlikely that we mean 1900, and certainly 002 is more likely to refer to 2002 than 1002. First of all, I suggest that definitions with 'holes' like maketime(,1,,,15,) should be rejected. An incomplete time definition should at least contain all the digits from its LSD to its MSD. As I said, the undefined values to the right of the defined stuff should be set to minimum values. maketime(1965,,,,,) should mean maketime(1965,1,1,0,0,0). When there are undefined values to the left of the indicated ones, I suggest they are assumed to be _as_close_as_ _possible_ to the current time. In other words, writing maketime(,,1,,,) on the coming christmas eve should mean 1998,1,1,0,0,0. This makes the module sane for handling things like maketime(65,01,01,12,20,) for my birth, maketime(924,7,8,,,) for my father's birth date, maketime(15,,,,,) for my 50th birthday (well, 51st really ;-) without having to use 4 digits for years that are close to today. So, if it's (1997,12,16,11,58,00) now and someone enters (,,1,,,) this should either be interpreted as t1=(1997,12,1,0,0,0) or t2=(1998,1,1,0,0,0). Then the actual time should be: entered_time = self.tuple t = entered_time.fill_min_values_after() #Zeroes except 1 for month and day t1 = t.fill_in_present_values_before() #Start with now and overwrite w/ t if t1 < now: t2 = t.fill_in_next(t1) #Next time after t1 that matches t else: t2 = t1 t1 = t.fill_in_previous(t2) if (now - t1 > t2 -now): t = t2 else: t = t1 Then we come back to the varying lenght of the month... (Maybe it wouldn't be a bad idea to try to move earth after all? ;-) If someone enters (,,31,23,59,59) on now=(1998,3,1,4,0,0), what do they refer to? (1998,1,31,23,59,59) is the closest, and (1998,3,31,23,59,59) is the next, but one could also imagine that they really wanted (1998,2,28,23,59,59), just as we might assume that one month after Jan 31 is Feb 28. In a way I could imagine having (,-1,,,,) meaning the last day of the month, just as x[-1], but on the other hand, that's not really a KISS approach... OUCH! I just realized a significant problem! If year is an integer, there is no way of differentiating 8 (which should mean 1998) and 08 (which should mean 2008)! I think this is a problem of some significance. I can only see three solutions to that, and all are ugly: 1) use strings (that would make it possible to parse month names I guess) 2) add an extra value to indicate how many digits are valid in year: 2,8 => 08 => 2002; 1,8 => 8 => 1998. 3) Make year into four tuple instances instead of one 1997 => 1,9,9,7 I guess this is really just an issue when we are parsing input, and in that case the string is what we start with anyway. Maybe this don't have anything to do in the date base class at all. Maybe this parsing should be a function that the entry widgets or input file parsers should call before saving a date. -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timehorse@unforgettable.com Tue Dec 16 15:33:55 1997 From: timehorse@unforgettable.com (Jeffrey C. Jacobs) Date: Tue, 16 Dec 1997 10:33:55 -0500 Subject: [DB-SIG] Assuming larger time scope Message-ID: <01BD0A0E.1FFBFDB0@aceltd0185.aceltd.com> -----Original Message----- From: Magnus Lycka [SMTP:magnus.lycka@tripnet.se] Sent: Tuesday, December 16, 1997 6:45 AM To: DB-SIG @ Python.org Subject: [DB-SIG] Assuming larger time scope First of all, I suggest that definitions with 'holes' like maketime(,1,,,15,) should be rejected. An incomplete time definition should at least contain all the digits from its LSD to its MSD. As I said, the undefined values to the right of the defined stuff should be set to minimum values. maketime(1965,,,,,) should mean maketime(1965,1,1,0,0,0). When there are undefined values to the left of the indicated ones, I suggest they are assumed to be _as_close_as_ _possible_ to the current time. In other words, writing maketime(,,1,,,) on the coming christmas eve should mean 1998,1,1,0,0,0. This makes the module sane for handling things like maketime(65,01,01,12,20,) for my birth, maketime(924,7,8,,,) for my father's birth date, maketime(15,,,,,) for my 50th birthday (well, 51st really ;-) without having to use 4 digits for years that are close to today. [The TimeHorse] One thing I would suggest is that the month interpolation need not be so complicated as rounding to the nearest date. Probably in such cases where the month is left blank to fill in the month with the current month. Certainly, in a lot of circumstances I might mean the last "first of the month", say if I wanted to keep track of when my mother last visited, and sometimes I'd want to interpolate to the next "first of the month", when my rent is due. Thus, for simplicity, I'd just suggest use the current month. [End TimeHorse] Then we come back to the varying lenght of the month... (Maybe it wouldn't be a bad idea to try to move earth after all? ;-) If someone enters (,,31,23,59,59) on now=(1998,3,1,4,0,0), what do they refer to? (1998,1,31,23,59,59) is the closest, and (1998,3,31,23,59,59) is the next, but one could also imagine that they really wanted (1998,2,28,23,59,59), just as we might assume that one month after Jan 31 is Feb 28. [The TimeHorse] In this case, I think most applications let the date spill over into the next month. Thus (,,31,,,) in February 1998 would evaluate to 3 March 1998. [End TimeHorse] In a way I could imagine having (,-1,,,,) meaning the last day of the month, just as x[-1], but on the other hand, that's not really a KISS approach... [The TimeHorse] This would be a good way of solving the whole last of the month issue when we add months. A shame we can't make a distinction between the 31st of January and the last day of January. When adding a month to it, this is a big issue. Agreed, though: it is a can of worms! [End TimeHorse] OUCH! I just realized a significant problem! If year is an integer, there is no way of differentiating 8 (which should mean 1998) and 08 (which should mean 2008)! I think this is a problem of some significance. I can only see three solutions to that, and all are ugly: 1) use strings (that would make it possible to parse month names I guess) 2) add an extra value to indicate how many digits are valid in year: 2,8 => 08 => 2002; 1,8 => 8 => 1998. 3) Make year into four tuple instances instead of one 1997 => 1,9,9,7 [The TimeHorse] One issue I would point out even more so is that there is always *some* way of entering any date in the 20th and 21 centuries if we just type it out fully, but if we allow abbreviations, such as even '98, how do I know I don't mean 98 AD? It is quite possible, even if unlikely that I wish to enter a date of that type, and by allowing abbreviation we have eliminated *any* way of entering such a date. I think the easiest thing to do is to force the user to write out the date in full, as that is the best way I can think of to also allow input of small dates. At the very least, we need to have some method of entering small dates, such as 98 AD [End TimeHorse] Be Seeing You, Jeffrey. --- ~,-;` The TimeHorse Sometimes also a Dragon. . . _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Tue Dec 16 18:03:45 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Tue, 16 Dec 1997 19:03:45 +0100 Subject: [DB-SIG] Assuming larger time scope References: <349152C1.1416866A@uni-duesseldorf.de> <3.0.1.32.19971214011023.007667d0@mail1.tripnet.se> <34946226.7142A065@uni-duesseldorf.de> <3.0.1.32.19971216124446.006aeda0@mail1.tripnet.se> <34968F8C.73A0EAAE@uni-duesseldorf.de> Message-ID: <3496C280.4FBF6F41@uni-duesseldorf.de> Magnus Lycka wrote: > > [Omitting entries in maketime()] > > In a way I could imagine having (,-1,,,,) meaning the last day of the month, > just as x[-1], but on the other hand, that's not really a KISS approach... I've already added that feature (using -1 for the last day of the month, -2 for the day before that and so on). It is quite useful in some cases where you'd otherwise have to do the day calculation yourself. I'll also add a function that returns the day lengths for the months in a given year. > > I guess this is really just an issue when we are parsing input, and in that > case the string is what we start with anyway. Maybe this don't have anything > to do in the date base class at all. Maybe this parsing should be a function > that the entry widgets or input file parsers should call before saving a > date. Right. This certainly belongs in some fuzzy date/time parsing module. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Wed Dec 17 10:04:07 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Wed, 17 Dec 1997 11:04:07 +0100 Subject: [DB-SIG] Assuming larger time scope References: <01BD0A0E.1FFBFDB0@aceltd0185.aceltd.com> Message-ID: <3497A397.66071F9F@uni-duesseldorf.de> Jeffrey C. Jacobs wrote: > > -----Original Message----- > From: Magnus Lycka [SMTP:magnus.lycka@tripnet.se] > Sent: Tuesday, December 16, 1997 6:45 AM > To: DB-SIG @ Python.org > Subject: [DB-SIG] Assuming larger time scope > ... > Then we come back to the varying lenght of the month... (Maybe it wouldn't > be a bad idea to try to move earth after all? ;-) If someone enters > (,,31,23,59,59) on now=(1998,3,1,4,0,0), what do they refer to? > (1998,1,31,23,59,59) is the closest, and (1998,3,31,23,59,59) is the next, > but one could also imagine that they really wanted (1998,2,28,23,59,59), > just as we might assume that one month after Jan 31 is Feb 28. > > [The TimeHorse] In this case, I think most applications let > the date spill over into the next month. Thus (,,31,,,) in > February 1998 would evaluate to 3 March 1998. > [End TimeHorse] Not so the next version of DateTime. It checks the day of the month and raises an exception if it doesn't fit the given month. > In a way I could imagine having (,-1,,,,) meaning the last day of the month, > just as x[-1], but on the other hand, that's not really a KISS approach... > > [The TimeHorse] This would be a good way of solving the > whole last of the month issue when we add months. A shame > we can't make a distinction between the 31st of January > and the last day of January. When adding a month to it, > this is a big issue. Agreed, though: it is a can of worms! > [End TimeHorse] I've added the -1 (last day of the month) feature to maketime(). It will get converted to the real day though, so the "last day of the month" information is lost after initialization. But it is still useful for doing the exception handling I pointed out in another post. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From jim.fulton@digicool.com Wed Dec 17 21:20:58 1997 From: jim.fulton@digicool.com (Jim Fulton) Date: Wed, 17 Dec 1997 16:20:58 -0500 Subject: [DB-SIG] ODMG Date/time classes Message-ID: <3498423A.3EDE@digicool.com> This is a multi-part message in MIME format. --------------470D371E61B2 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit As promised, I'm providing skeleton python classes that describe the interfaces to the standard date-time related types defined by the Object Data Management Group (ODMG) standard. I beleave these are based on possibly SQL standards, although I can't provide a reference. I prefer this interface to the interface proposed by M.-A. Lemburg because: - It is a standard, - It handles time zones in a reasonable minimal manner, - It provides for separation of date, time, and interval, - It supports date/time arithmetic, - It provides information hiding (the implementation is not exposed) Jim -- Jim Fulton mailto:jim@digicool.com Technical Director (888) 344-4332 Python Powered! Digital Creations http://www.digicool.com http://www.python.org --------------470D371E61B2 Content-Type: text/plain; charset=us-ascii; name="ODMG-Date.py" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="ODMG-Date.py" class Interval: """Duration of time The Interval class is used to represent a duration of time. It is also used to perform arithmetic operations on Date, Time, and Timestamp classes. This class corresponds to the date-time interval as defined in the SQL standard. The Interval class accepts nonnormalized input, but normalizes the time components when accessed. For example, the constructor would accept 28 hours as input, but then calling the day method would return a value of 1 and the hour method would return a value of 4. Arithmetic would work in a similar manner. """ def __init__(self, day=0, hour=0, min=0, sec=0.0): """Initialize an Interval An alternate signature may be used to initialize an Interval from an existing Interval: Interval(anInterval) """ def day(self): """Return the day part of the interval" def hour(self): """Return the hour part of the interval" def minute(self): """Return the minute part of the interval" def second(self): """Return the seconds part of the interval" def is_zero(self): """Return true if all of the interval parts are zero Return false otherwise. """ def __nonzero__(self): """Return true if any of the interval parts are nonzero Return false otherwise. """ def __neg__(self): """Return the Interval negated""" def __pos__(self): """Return the Interval""" def __add__(self, anInterval): """Add two intervals""" def __sub__(self, anInterval): """Subtract two intervals""" def __mul__(self, anInt): """Multiply an interval by an integer""" __rmul__=__mul__ def __div__(self, anInt): """Divide an interval by an integer""" def __mod__(self, anInt): """Return the remainder of division by an integer""" def __divmod__(self, anInt): """Return the result and remainder of division by an integer""" def __cmp__(self, anInterval): """Compare two intervals""" def __hash__(self): """Return a hash value""" class _DateStatic: """Static Date functions This class is not a part of the public interface, but the methods defined below are "static" methods of the (public) Date class. """ def current(self): """Return the current date" def is_leap_year(self, year): """Return true if the given year is a leap year, and false otherwise" def days_in_year(self, year): """Return the number of days in the year" def days_in_month(self, year, month): """Return the number of days in the month of the year" def is_valid_date(self, year, month, day): """Test whether the given year, month, and day are valid" _DateStatic=_DateStatic() class Date: """Dates The Date class stores a representation of a date consisting of a year, month and day. It also provides enumerations to denote weekdays and months. Days within a month or year are numbered from 1, as are months. """ [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday ] = range(7) [January, February, March, April, May, June, July, August, September, October, November, December ] = range(1,13) def __init__(self, *args): """Initialize a date A number of different signatures are supported: Date() -- Initialize to the current date. Date(aDateOrTimestamp) -- Initialize from an existing Date or Timestamp Date(aTimeTime) -- Initialize from a value of the type returned by the 'time' function of the 'time' module. Date(year, day_of_year) -- Initialize from a year and a day within the year. Date(year, month, day) -- initialize from a year, month, and day. if the specified date inputs are invalid, a DateInvalidError exception is raised. """ def year(self): """Return the year component of the date""" def month(self): """Return the month component of the date""" def day(self): """Return the day (in the month) component of the date""" def day_of_year(self): """Return the day within the year""" def day_of_week(self): """Return the day within the week as an integer""" month_of_year=month def is_leap_year(self): """Return true if the date\'s year is a leap year, and false otherwise" def next(self, aDayOfWeek): """Advance the date to the next date that falls on the day of the week The date is modified and returned" def previous(self, aDayOfWeek): """Back the date to the next date that falls on the day of the week The date is modified and returned" def increment(self, days): """Advance the date the given number of days The date is modified and returned" def deccrement(self, days): """Back the date the given number of days The date is modified and returned" def __add__(self, anInterval): """Add an Interval, returning a new Date""" __radd__=__add__ def __sub__(self, anIntervalOrDate): """Subtract a Date or an Interval If subtracting an Interval, a Date is returned. If subtracting a Date, an Interval is returned. """ def __cmp__(self, aDate): """Compare two dates""" def __hash__(self): """Return a hash code""" def is_between(self, aDate, anotherDate): """Return true if the date is between 'aDate' and 'anotherdate'. Return false otherwise. """ def days_in_year(self): """Return the number of days in the year" def days_in_month(self): """Return the number of days in the month" current=_DateStatic.current is_leap_year=_DateStatic.is_leap_year days_in_year=_DateStatic.days_in_year days_in_month=_DateStatic.days_in_month is_valid_date=_DateStatic.is_valid_date class DateInvalidError: """Exception class for invalid date creation parameters""" class _TimeStatic: """Static Time Functions This class is not a part of the public interface, but the methods defined below are "static" methods of the (public) Time class. """ def default_Time_Zone(self): """Get the default time zone hours offset""" def default_Time_Zone_minutes(self): """Get the default time zone minutes offset""" def set_default_Time_Zone(self, hours, minutes=0): """Set the default time zone (offset from GMT)""" def set_default_Time_Zone_to_local(self): """Set the default time zone to the local time zone""" def current(): """Return the current time as a Time using the default time zone" _TimeStatic=_TimeStatic() class Time: """Denote a specific time The Time class is used to denote a specific time, which is internally stored in Greenwich Mean Time (GMT). """ [ GMT_11, GMT_10, GMT_9, GMT_8, GMT_7, GMT_6, GMT_5, GMT_4, GMT_3, GMT_2, GMT_1, GMT, GMT1, GMT2, GMT3, GMT4, GMT5, GMT6, GMT7, GMT8, GMT9, GMT10, GMT11, ] range(-11,12) USeastern, UScentral, USmountain, USpacific = -5, -6, -7, -8 def __init__(self, *args): """Initialize a Time A number of different signatures are supported: Time() -- initialize to current time (and default time zone) Time(aTimeOrTimestamp) -- Initialize from a Time or Timestamp Time(hour, minute, second=0, tz_hour=None, tz_minute=None) -- Initialize from given hour, minute, second, and time-zone offset in hours and minutes. If the time zone is not specified, then the default time zone is used. If tz_hour is specified, then tz_minute defaults to 0. """ def hour(self): "Return the hour component of the Time" def minute(self): "Return the minute component of the Time" def second(self): "Return the second component of the Time" def tz_hour(self): "Return the time-zone hour component" def tz_minute(self): "Return the time-zone minute component" def __add__(self, anInterval): """Add an Interval""" __radd__=__add__ def __sub__(self, anIntervalOrTime): """Subtract a Time or an Interval If a Time is subtracted, then an Interval is returned. If an Interval is subtracted, then a Time is returnd (modulo 24 hours). """ def __cmp__(self, aTime): """Compare two Times""" def __hash__(self): """Return a hash code""" class TimeInvalidError: """Exception class for invalid Time creation parameters""" default_Time_Zone=_TimeStatic.default_Time_Zone set_default_Time_Zone=_TimeStatic.set_default_Time_Zone set_default_time_Zone_to_local=_TimeStatic.set_default_Time_Zone_to_local current=_TimeStatic.current class _TimestampStatic: """Static Timestamp Functions This class is not a part of the public interface, but the methods defined below are "static" methods of the (public) Timestamp class. """ def current(): """Return the current time as a Timestamp" _TimestampStatic=_TimestampStatic() class Timestamp: """A Timestamp models a point in time as a Date and a Time""" def __init__(self, *args): """Initialize a Timestamp A number of different signatures are supported: Timestamp() -- Initialize to current time, using the default time zone. Timestamp(year, month=1, day=1, hour=0, minute=0, second=0.0, tzhours=None, tzminutes=None) -- Initialize from a year, month, day, hour, minute, and time zone. If the time zone is not specified, then the default time zone is used. If tzhours is specified, then tzminutes defaults to 0. Timestamp(aDate, aTime) -- Initialize from a Date and Time Timestamp(Timestamp) -- Initialize from a Timestamp Timestamp(aTimeTime, tzhours=None, tzminutes=None) -- Initialize from a value of the type returned by the 'time' function of the 'time' module, and the local time zone. If the time zone is not specified, then the default time zone is used. If tzhours is specified, then tzminutes defaults to 0. """ def date(self): """Return the Date component" def time(self): """Return the time component" def year(self): """Return the year component of the date""" def month(self): """Return the month component of the date""" def day(self): """Return the day (in the month) component of the date""" def hour(self): "Return the hour component of the Time" def minute(self): "Return the minute component of the Time" def second(self): "Return the second component of the Time" def tz_houre(self): "Return the time-zone hour component" def tz_minute "Return the time-zone minute component" def __add__(self, anInterval): """Add an Interval""" __radd__=__add__ def __sub__(self, anIntervalOrTime): """Subtract a Timestamp or an Interval""" def __cmp__(self, aTimestamp): """Compare two Timestamps""" def __hash__(self): """Return a hash code""" class TimestampInvalidError: """Exception class for invalid Timestamp creation parameters""" current=_TimeStatic.current def overlaps(s1,e1,s2,e2): """Determine wether two periods overlap. The first period is defined by either two Dates, two Times, or two Timestamps s1, and e1. The second period is defined by either two Dates, two Times, or two Timestamps s1, and e1. This function is not defined for combinations of two Dates and two Times. """ --------------470D371E61B2-- _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From magnus.lycka@tripnet.se Thu Dec 18 09:18:15 1997 From: magnus.lycka@tripnet.se (Magnus Lycka) Date: Thu, 18 Dec 1997 10:18:15 +0100 Subject: [DB-SIG] ODMG Date/time classes In-Reply-To: <3498423A.3EDE@digicool.com> Message-ID: <3.0.1.32.19971218101815.00764f48@mail1.tripnet.se> At 16:20 1997-12-17 -0500, Jim Fulton wrote: > def __mul__(self, anInt): > """Multiply an interval by an integer""" > > __rmul__=3D__mul__ > > def __div__(self, anInt): > """Divide an interval by an integer""" Why not allow floats? I assume you've just copied the standard, but what would be the reason for not allowing mult and div with floats? Seconds is float, so division should handle a floating point result anyway. It seems like an arbitrary restriction.=20 I'm not quite sure what integer divition and remainder would mean for a time interval. If it had just been defined as days I would get it, but since it is defined to fractions of seconds... I think mod and divmod mistakes. They really only make sense when both nominator and denominator are integers. They don't make sense when the interval is a compound where it's unclear what the unit is. Somehow, it seems that if t =3D 5 days, then t div 2 =3D 2 and t rem 2 =3D= 1, but t =3D 5 days =3D 120 hours =3D> t div 2 =3D 60 hours (=3D 2=BD days), t= mod 2 =3D 0!!!=20 > [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday > ] =3D range(7) This seems to contradict the ISO standard which starts with Monday. There were just Americans in the group that developed this, right? ;-) Date could certainly benefit from having methods ISO_year() and ISO_week(). We use week numbers frequently in Sweden for instance. If a pocket or wall calender lacked week numbers it would certainly be considered flawed. It would also be good to have methods for Date and Timestamp that returned aTimeTime, so that integration with the time module can work both ways. This somehow needs to handle TZ. localtime() and gmtime() I guess. Magnus PS In Lithuanian (my wife's mother tongue) Monday is pirmadienis (first day), Tuesday is antradienis (second day) and so on. No discussion about which day the week starts with. :-) No, Sunday is not nuliadienis, it's sekmadienis (seventh day)! -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Thu Dec 18 11:13:15 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Thu, 18 Dec 1997 12:13:15 +0100 Subject: [DB-SIG] ODMG Date/time classes References: <3498423A.3EDE@digicool.com> Message-ID: <3499054B.9CD2616@uni-duesseldorf.de> Jim Fulton wrote: > > As promised, I'm providing skeleton python classes that > describe the interfaces to the standard date-time related > types defined by the Object Data Management Group (ODMG) > standard. I beleave these are based on possibly SQL standards, > although I can't provide a reference. > > I prefer this interface to the interface proposed by M.-A. Lemburg > because: > > - It is a standard, > > - It handles time zones in a reasonable minimal manner, > > - It provides for separation of date, time, and interval, > > - It supports date/time arithmetic, > > - It provides information hiding (the implementation is not > exposed) > I can't see that many differences between what you're exposing there and what I'm currently doing. You could very well use my DateTime-type as internal basis for all your classes, since nearly all features you have provided skeletons for are already available as methods or instance variables. Some things are still missing, like hashing, comparing, etc. but they'll be added soon. I left the timezone and DST out on purpose, since I feel that a simple enough type can easily be extended in any particular way. The date/time arithmetic will be in one of the next versions, once I find some time to code them up. It looks like you are only providing absolute time differences, is that correct ? I'm asking because I still haven't decided yet on introducing one or two types for intervalls -- maybe the absolute one in C and the relative one in Python (since there are dozens of different way these can be implemented). Together with your suggested C object wrapping of the C API it is a piece of cake to adapt any DB interface to use the type -- that's why I coded it up in C after all. BTW, that wrapping method is really ingenious, you should promote that more often :-) -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Thu Dec 18 12:39:08 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Thu, 18 Dec 1997 13:39:08 +0100 Subject: [DB-SIG] ODMG Date/time classes References: <3498423A.3EDE@digicool.com> <3499054B.9CD2616@uni-duesseldorf.de> Message-ID: <3499196C.353A4BC1@uni-duesseldorf.de> An aside: I'll make new constructor names available in the next version (in an effort to be compatible to the ODMG standard Jim wrote about) new old --------------------------------------------------- Timestamp maketime Date maketime without time part DateTimeFromTicks maketime_fromticks DateTimeFromCOMDate maketime_fromCOMDate The old names will continue too work. You might have noticed a missing Time constructor. That's because time is always relative to a date and thus needs to be an instance of RelativeDateTime with the date part set to 0. To Jim: The date/time objects will have to go through the dbi abstraction module anyway, so we can have plurality on the user side as long as you provide methods for converting your instances to DateTime ones (or did you plan to implement the instances in C too ?) which the DB interface can then use. You should also provide methods and constructors for the "absolute date" that Christian Egli's classes use to make them usable on top of your classes. BTW, is Christian going to upload his work to some URL out there ? Would be nice if we could at least reference them. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From christian.egli@stest.ch Thu Dec 18 14:03:25 1997 From: christian.egli@stest.ch (Christian Egli) Date: 18 Dec 1997 15:03:25 +0100 Subject: [DB-SIG] ODMG Date/time classes In-Reply-To: "M.-A. Lemburg"'s message of Thu, 18 Dec 1997 13:39:08 +0100 References: <3498423A.3EDE@digicool.com> <3499054B.9CD2616@uni-duesseldorf.de> <3499196C.353A4BC1@uni-duesseldorf.de> Message-ID: >>>>> "Marc" == M -A Lemburg writes: Marc> BTW, is Christian going to upload his work to some URL out Marc> there ? Would be nice if we could at least reference them. 1. I don't have an URL where I could put my stuff. 2. I don't really like my code all that much. The class hierarchy bugs me because I have to convert a GregorianDate into an AbsoluteDate into an IsoDate just to find out the weekInYear. What I really want is for the GregorianDate object to change its interface and become an IsoDate. How could I achieve that? Is aggregation maybe the key? 3. Least but not last we haven't decided on a decent name. I first used the same name as Edward M. Reingold, namely CalendricalCalculations.py but this seems too long and awkward. But if you'd like to upload it to some URL (maybe ftp.python.org?) feel free to do so. -- Christian Egli Switching Test Solutions AG, Friesenbergstr. 75, CH-8055 Zuerich _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From christian.egli@stest.ch Thu Dec 18 14:15:11 1997 From: christian.egli@stest.ch (Christian Egli) Date: 18 Dec 1997 15:15:11 +0100 Subject: [DB-SIG] ODMG Date/time classes In-Reply-To: Magnus Lycka's message of Thu, 18 Dec 1997 10:18:15 +0100 References: <3.0.1.32.19971218101815.00764f48@mail1.tripnet.se> Message-ID: >>>>> "Magnus" == Magnus Lycka writes: >>>>> At 16:20 1997-12-17 -0500, Jim Fulton wrote: >> [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday ] >> = range(7) Magnus> This seems to contradict the ISO standard which starts with Magnus> Monday. There were just Americans in the group that Magnus> developed this, right? ;-) This could easily be overwritten in a subclass IsoDate. Magnus> Date could certainly benefit from having methods ISO_year() Magnus> and ISO_week(). Which could also be provided by the subclass IsoDate. -- Christian Egli Switching Test Solutions AG, Friesenbergstr. 75, CH-8055 Zuerich _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From christian.egli@stest.ch Thu Dec 18 14:14:53 1997 From: christian.egli@stest.ch (Christian Egli) Date: 18 Dec 1997 15:14:53 +0100 Subject: [DB-SIG] ODMG Date/time classes In-Reply-To: Jim Fulton's message of Wed, 17 Dec 1997 16:20:58 -0500 References: <3498423A.3EDE@digicool.com> Message-ID: >>>>> "Jim" == Jim Fulton writes: Jim> As promised, I'm providing skeleton python classes that Jim> describe the interfaces to the standard date-time related types Jim> defined by the Object Data Management Group (ODMG) standard. I Jim> beleave these are based on possibly SQL standards, although I Jim> can't provide a reference. Jim> I prefer this interface to the interface proposed by Jim> M.-A. Lemburg because: Jim> - It is a standard, Jim> - It handles time zones in a reasonable minimal manner, Jim> - It provides for separation of date, time, and interval, Jim> - It supports date/time arithmetic, Jim> - It provides information hiding (the implementation is not Jim> exposed) I like it. My only question is: What can I do to get an implementation happening? -- Christian Egli Switching Test Solutions AG, Friesenbergstr. 75, CH-8055 Zuerich _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Thu Dec 18 16:26:52 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Thu, 18 Dec 1997 17:26:52 +0100 Subject: [DB-SIG] mxDateTime version 0.3 prerelease References: <349152C1.1416866A@uni-duesseldorf.de> Message-ID: <34994ECC.2FCFC8A1@uni-duesseldorf.de> I've changed the way you can interface to the mxDateTime module, so that it should now be usable as basis for DB interface extensions: http://starship.skyport.net/~lemburg/mxDateTime.html Version 0.4 will have the date/time calculations and the second basic type: RelativeDateTime. The extension will then be wrapped by a Python module and provide some additional classes on top of the two C types. Please have a look and give me feedback about portability issues. I haven't heard much from you in that direction yet. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From lemburg@uni-duesseldorf.de Thu Dec 18 16:12:53 1997 From: lemburg@uni-duesseldorf.de (M.-A. Lemburg) Date: Thu, 18 Dec 1997 17:12:53 +0100 Subject: [DB-SIG] ODMG Date/time classes References: <3498423A.3EDE@digicool.com> <3499054B.9CD2616@uni-duesseldorf.de> <3499196C.353A4BC1@uni-duesseldorf.de> Message-ID: <34994B85.3F999396@uni-duesseldorf.de> Christian Egli wrote: > > >>>>> "Marc" == M -A Lemburg writes: > > Marc> BTW, is Christian going to upload his work to some URL out > Marc> there ? Would be nice if we could at least reference them. > > 1. I don't have an URL where I could put my stuff. You could get one for $50 / year :-) Ask Christian Tismer. But that left aside, everybody can upload code to ftp.python.org/incoming. There are instructions for uploading on the FTP server too. After a few days someone (I guess Ken does this) will move the package to one of the contrib directories. > > 2. I don't really like my code all that much. The class hierarchy bugs > me because I have to convert a GregorianDate into an AbsoluteDate > into an IsoDate just to find out the weekInYear. What I really want > is for the GregorianDate object to change its interface and become > an IsoDate. How could I achieve that? Is aggregation maybe the key? You could code that up directly (as I see it you only use this in one place) instead of creating two intermediate dates. > 3. Least but not last we haven't decided on a decent name. I first > used the same name as Edward M. Reingold, namely > CalendricalCalculations.py but this seems too long and awkward. Why not just Calendars.py ? I think writing 'from Calendars import GregorianDate' is straight forward enough. -- Marc-Andre Lemburg _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timehorse@unforgettable.com Thu Dec 18 17:25:48 1997 From: timehorse@unforgettable.com (Jeffrey C. Jacobs) Date: Thu, 18 Dec 1997 12:25:48 -0500 Subject: [DB-SIG] ODMG Date/time classes Message-ID: <01BD0BB0.1301DA00@aceltd0185.aceltd.com> -----Original Message----- From: Magnus Lycka [SMTP:magnus.lycka@tripnet.se] Sent: Thursday, December 18, 1997 4:18 AM To: Jim Fulton; db-sig@python.org Subject: Re: [DB-SIG] ODMG Date/time classes At 16:20 1997-12-17 -0500, Jim Fulton wrote: > def __mul__(self, anInt): > """Multiply an interval by an integer""" > > __rmul__=3D__mul__ > > def __div__(self, anInt): > """Divide an interval by an integer""" Why not allow floats? I assume you've just copied the standard, but what would be the reason for not allowing mult and div with floats? Seconds is float, so division should handle a floating point result anyway. It seems like an arbitrary restriction.=20 I'm not quite sure what integer divition and remainder would mean for a time interval. If it had just been defined as days I would get it, but since it is defined to fractions of seconds... I think mod and divmod mistakes. They really only make sense when both nominator and denominator are integers. They don't make sense when the interval is a compound where it's unclear what the unit is. Somehow, it seems that if t =3D 5 days, then t div 2 =3D 2 and t rem 2 = =3D 1, but t =3D 5 days =3D 120 hours =3D> t div 2 =3D 60 hours (=3D 2=BD = days), t mod 2 =3D 0!!!=20 [The TimeHorse] IMHO, I see this as an issue of units. Imagine we talk just about seconds for a moment. Remember "1 sec" is not the same as = "1". "1 sec" + "1" is "1 sec + 1", not "2 sec". What I'm getting at is, from = a scientific POV, "sec", "min", "day", etc are all conversion factors. In = a way, you can think of them as variable unknowns. In effect, when we say "1 sec", we in a sense mean "1 * sec". Thus, to combine terms, seconds can only be added or subtracted to seconds, and so on. Of course, since there are conversion factors, such as "1 min =3D 60 sec" =3D> "(1 min) / = (60 sec) =3D 1", and any number times 1 is equal to itself, we have "120 sec" =3D> "(120 sec) * 1" =3D> "120 sec * ((1 min) / (60 sec))" =3D> "(1 min) * ((120 sec) / (60 sec))" =3D> "(1 min) * (120 / 60)" =3D> "2 min" Thus, "1 min + 120 sec" does make sense, and is "3 min". Yeah, yeah! I know this is stuff we all learned in High School, but I just wanted to = set up for the basis of my thoughts. Anyway, extending this logic to multiplication, obviously units can cancel. Thus, "(120 sec) / (60 sec)" =3D> "2", since the "sec" cancels. Thus, when you divide a TimeSpan by a TimeSpan, you produce a clearly- defined number. There are exactly 2 "60 sec" in "120 sec". Equally, = when you multiply back, "2 * 60 sec =3D 120 sec", producing a TimeSpan from a TimeSpan. However, "1 sec * 1 sec =3D 1 sec^2", which is really beyond = the scope of what we want to support with DateTime, and thus should be disallowed. Equally, "2 / (1 sec) =3D 2 sec^-1" makes as little sense = as "1 sec^2", and thus should also be disallowed. However, "120 sec / 2 =3D = 60 sec" is just as valid as "(120 sec) / (60 sec) =3D 2". Thus, so far: Parameter ----------------Produces--------------- __mul__ __rmul__ __div__ __rdiv__ TimeSpan Exception Exception Number Number Number TimeSpan TimeSpan TimeSpan Exception Of course, I am only talking about TimeSpans here; multiplication and divisions by an Absolute Date really don't make much sense, since they = do not take into account the Epoch. For the Modulo operation, we have the definition: a / b =3D c; a % b =3D d =3D> a - d =3D b * c. Thus d, the result of the Modulo, must always be of the same type as a. Since we can not subtract a Number from a TimeSpan, if a, the left-hand Side of the Modulo, is a TimeSpan, then d, the result of the modulo must be so as well, irregardless of the type of b. However, as I mentioned above, a may not be a Number if b is a TimeSpan because then c becomes invalid. Thus, finally we have: Parameter --------------------------Produces------------------------- __mul__ __rmul__ __div__ __rdiv__ __mod__ __rmod__ TimeSpan Exception Exception Number Number TimeSpan TimeSpan Number TimeSpan TimeSpan TimeSpan Exception TimeSpan Exception Specifically, "(130 sec) % (1 min)" =3D> "(130 sec) % 60" =3D> "10 sec". Anyway, that's my opinion as to how the multiply-order operations should work. As for Number, I agree that Floats, Ints as well as Longs should be allowed, as long as we are consistent. The only problem I see with what Number type to use is for TimeSpan / TimeSpan, which will produce a Number of an unknown type. Certainly, in this case, a float would be useful for its support of decimals, but a Long is allows = infinite precision of integers, so I guess the best result would depend on the context. Again, sorry that so much of this is common-knowledge. I just couldn't resist codifying it here to make things easier. Be Seeing You, Jeffrey. --- ~,-;` The TimeHorse Sometimes also a Dragon. . . _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From magnus.lycka@tripnet.se Thu Dec 18 22:22:04 1997 From: magnus.lycka@tripnet.se (Magnus Lycka) Date: Thu, 18 Dec 1997 23:22:04 +0100 Subject: [DB-SIG] ODMG Date/time classes In-Reply-To: <01BD0BB0.1301DA00@aceltd0185.aceltd.com> Message-ID: <3.0.1.32.19971218232204.0077ca34@mail1.tripnet.se> Jeffrey C. Jacobs wrote: >Specifically, > > "(130 sec) % (1 min)" => > "(130 sec) % 60" => > "10 sec". But what about "(5 days) % (2 integer)" ? It seems intuitive that the 'unit' here would be 'days', but what we are doing is just (432000 sec) % (2 integer) which is not 2 days, but 2.5 days. Magnus -- Magnus Lycka, S/W Engineer, M.Sc.E.E; Folktrov. 6C, 907 51 Umea, Sweden Tel: +46(0)90 198 498, GSM: +46(0)70 582 80 65, Fax: +46(0)70 612 80 65 _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From timehorse@unforgettable.com Thu Dec 18 23:03:31 1997 From: timehorse@unforgettable.com (Jeffrey C. Jacobs) Date: Thu, 18 Dec 1997 18:03:31 -0500 Subject: [DB-SIG] ODMG Date/time classes Message-ID: <01BD0BDF.43FA4690@aceltd0185.aceltd.com> -----Original Message----- From: Magnus Lycka [SMTP:magnus.lycka@tripnet.se] Sent: Thursday, December 18, 1997 5:22 PM To: Jeffrey C. Jacobs; 'The Python DataBase Sig' Subject: RE: [DB-SIG] ODMG Date/time classes Jeffrey C. Jacobs wrote: >Specifically, > > "(130 sec) % (1 min)" =3D> > "(130 sec) % 60" =3D> > "10 sec". But what about "(5 days) % (2 integer)" ? It seems intuitive that the = 'unit' here would be 'days', but what we are doing is just (432000 sec) % (2 = integer) which is not 2 days, but 2.5 days. [The TimeHorse] Ah, ha!! I see your point! That is very well = observed, and since the second itself is a floating point value, the true = remainder of say "(1 sec) / 3" would be 0.000000000001 sec, which really is negligible. Thus, for TimeSpan values, we can always divide to a reasonably good precision. Really small TimeSpans would still be problematic because of the remainder being so large relative to the division result, but in most cases, the TimeSpan will be so large that = the error on division will be negligible compared to the result. The only time this might be a problem is if we define a TimeSpan as being a = series of distinct fields, such as months, days and years. I still think that the pure TimeSpan object should be an absolute time similar to the DateTime object, with the two, Day and SecondsSinceMidnight, fields, and thus can again be divided to relatively infinite precision. The only = time we would worry about the Modulo is when we deal with an object that = we want quantized to some unit, say such as months. Again, this is a question of TimeSpan implementation, and if we support the addition of months, then we also must somehow encode what our unit of quantization = is for the modulo arithmetic. Otherwise, with TimeSpans of floating-point precision, the modulo should always return "0 sec", or at most some very small error precision value, like +/- 0.000000000001 sec. Be Seeing You, Jeffrey. --- ~,-;` The TimeHorse Sometimes also a Dragon. . . _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________ From robert@directed.edu Wed Dec 24 17:47:11 1997 From: robert@directed.edu (robert@directed.edu) Date: Wed, 24 Dec 1997 12:47:11 -0500 Subject: [DB-SIG] P R E S S R E L E A S E Message-ID: DirectED - The New Way to Learn! DirectED is a distance education school that will revolutionize the way people will think about education in the future. Students can now study in the comfort of their own home to earn their diploma. What is unique about DirectED is that it is completely Internet based. Students attend classes in a virtual campus that has an employment center, library, cafeteria, computer lab, book store, faculty lounge, business office, student residence, and virtual classrooms. You can visit the campus at http://www.directed.edu. All DirectED Students will receive: Acer Multimedia Computer Lexmark Color Printer Windows 95 Office 97 Professional Books Prepaid Internet Connection for 1 Year Access to DirectED Web Site Toll Free Support for 1 Year DirectED programs are certified and registered with Department of Training and Advanced Education. DirectED is a member of the Better Business Bureau. DirectED partners include the Toronto Dominion Bank, MTS Sympatico, Acer, Course Technology, Microsoft, and Computer Associates. To find out more about THE NEW WAY TO LEARN please visit DirectED's business office at http://www.directed.edu/bus.html _______________ DB-SIG - SIG on Tabular Databases in Python send messages to: db-sig@python.org administrivia to: db-sig-request@python.org _______________