[Zope] y2kbug - bobobase_modification_time one day back
Brian Lloyd
Brian@digicool.com
Tue, 7 Mar 2000 13:43:55 -0500
This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.
------ =_NextPart_000_01BF8865.178AFB40
Content-Type: text/plain
> > People did report this bug elsewhere on the list.
> Apparently we're waiting
> > until monday when Jim Fulton can take a look at this.
> They're pretty sure
> > it's just a display problem and not something wrong with the object
> > database, but they want to make sure and check with Jim.
>
> Hi. How's Jim getting on with this? Apologies if I missed something
> on the list.
He has checked in the fix - if you are tracking CVS you need to
update lib/python/ZODB/TimeStamp.c and rebuild it. For those not
using CVS, I've attached a copy of the updated file to this email
(but you'll still have to rebuild the extension for the change to
take effect).
Brian Lloyd brian@digicool.com
Software Engineer 540.371.6909
Digital Creations http://www.digicool.com
------ =_NextPart_000_01BF8865.178AFB40
Content-Type: application/octet-stream;
name="TimeStamp.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="TimeStamp.c"
/***********************************************************************=
******=0A=
=0A=
Zope Public License (ZPL) Version 1.0=0A=
-------------------------------------=0A=
=0A=
Copyright (c) Digital Creations. All rights reserved.=0A=
=0A=
This license has been certified as Open Source(tm).=0A=
=0A=
Redistribution and use in source and binary forms, with or without=0A=
modification, are permitted provided that the following conditions =
are=0A=
met:=0A=
=0A=
1. Redistributions in source code must retain the above copyright=0A=
notice, this list of conditions, and the following disclaimer.=0A=
=0A=
2. Redistributions in binary form must reproduce the above =
copyright=0A=
notice, this list of conditions, and the following disclaimer =
in=0A=
the documentation and/or other materials provided with the=0A=
distribution.=0A=
=0A=
3. Digital Creations requests that attribution be given to Zope=0A=
in any manner possible. Zope includes a "Powered by Zope"=0A=
button that is installed by default. While it is not a license=0A=
violation to remove this button, it is requested that the=0A=
attribution remain. A significant investment has been put=0A=
into Zope, and this effort will continue if the Zope community=0A=
continues to grow. This is one way to assure that growth.=0A=
=0A=
4. All advertising materials and documentation mentioning=0A=
features derived from or use of this software must display=0A=
the following acknowledgement:=0A=
=0A=
"This product includes software developed by Digital =
Creations=0A=
for use in the Z Object Publishing Environment=0A=
(http://www.zope.org/)."=0A=
=0A=
In the event that the product being advertised includes an=0A=
intact Zope distribution (with copyright and license included)=0A=
then this clause is waived.=0A=
=0A=
5. Names associated with Zope or Digital Creations must not be used =
to=0A=
endorse or promote products derived from this software without=0A=
prior written permission from Digital Creations.=0A=
=0A=
6. Modified redistributions of any form whatsoever must retain=0A=
the following acknowledgment:=0A=
=0A=
"This product includes software developed by Digital =
Creations=0A=
for use in the Z Object Publishing Environment=0A=
(http://www.zope.org/)."=0A=
=0A=
Intact (re-)distributions of any official Zope release do not=0A=
require an external acknowledgement.=0A=
=0A=
7. Modifications are encouraged but must be packaged separately as=0A=
patches to official Zope releases. Distributions that do not=0A=
clearly separate the patches from the original work must be =
clearly=0A=
labeled as unofficial distributions. Modifications which do =
not=0A=
carry the name Zope may be packaged in any form, as long as =
they=0A=
conform to all of the clauses above.=0A=
=0A=
=0A=
Disclaimer=0A=
=0A=
THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY=0A=
EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
THE=0A=
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A =
PARTICULAR=0A=
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR =
ITS=0A=
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,=0A=
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT=0A=
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF=0A=
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED =
AND=0A=
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT =
LIABILITY,=0A=
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY =
OUT=0A=
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
OF=0A=
SUCH DAMAGE.=0A=
=0A=
=0A=
This software consists of contributions made by Digital Creations =
and=0A=
many individuals on behalf of Digital Creations. Specific=0A=
attributions are listed in the accompanying credits file.=0A=
=0A=
=
************************************************************************=
****/=0A=
=0A=
static char TimeStamp_module_documentation[] =3D =0A=
""=0A=
"\n$Id: TimeStamp.c,v 1.6 2000/03/06 21:09:14 jim Exp $"=0A=
;=0A=
=0A=
#include <stdlib.h>=0A=
#include <time.h>=0A=
#ifdef USE_EXTENSION_CLASS=0A=
#include "ExtensionClass.h"=0A=
#else=0A=
#include "Python.h"=0A=
#endif=0A=
=0A=
static PyObject *ErrorObject;=0A=
=0A=
/* ----------------------------------------------------- */=0A=
=0A=
static void PyVar_Assign(PyObject **v, PyObject *e) { Py_XDECREF(*v); =
*v=3De;}=0A=
#define ASSIGN(V,E) PyVar_Assign(&(V),(E))=0A=
#define UNLESS(E) if(!(E))=0A=
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E); UNLESS(V)=0A=
#define OBJECT(O) ((PyObject*)(O))=0A=
=0A=
/* Declarations for objects of type TimeStamp */=0A=
=0A=
typedef struct {=0A=
PyObject_HEAD=0A=
unsigned char data[8];=0A=
} TimeStamp;=0A=
=0A=
static double=0A=
TimeStamp_yad(int y)=0A=
{=0A=
double d, s;=0A=
=0A=
y -=3D 1900;=0A=
=0A=
d=3D(y-1)*365;=0A=
if (y > 0) =0A=
{=0A=
s=3D1.0;=0A=
y=3Dy-1;=0A=
}=0A=
else=0A=
{=0A=
s=3D-1.0;=0A=
y =3D -y;=0A=
}=0A=
return d+s*(y/4-y/100+(y+300)/400);=0A=
}=0A=
=0A=
static char month_len[2][12]=3D{=0A=
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, =0A=
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}=0A=
};=0A=
=0A=
static short joff[2][12] =3D {=0A=
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},=0A=
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}=0A=
};=0A=
=0A=
static double=0A=
TimeStamp_abst(int y, int mo, int d, int m, int s)=0A=
{=0A=
int l;=0A=
=0A=
l =3D y%4=3D=3D0 && (y%100 !=3D 0 || y%400=3D=3D0);=0A=
return (TimeStamp_yad(y)+ joff[l][mo]+d)*86400 + m*60 + s;=0A=
}=0A=
=0A=
static double gmoff=3D0, sconv=3D0;=0A=
=0A=
static int=0A=
TimeStamp_init_gmoff()=0A=
{=0A=
struct tm *t;=0A=
time_t z=3D0;=0A=
=0A=
t=3Dgmtime(&z);=0A=
if (! t)=0A=
{=0A=
PyErr_SetString(PyExc_SystemError, "gmtime failed");=0A=
return -1;=0A=
}=0A=
gmoff=3DTimeStamp_abst(=0A=
t->tm_year+1900, t->tm_mon, t->tm_mday-1, =0A=
t->tm_hour*60+t->tm_min, t->tm_sec);=0A=
=0A=
sconv=3D((double)60)/((double)(1<<16))/((double)(1<<16));=0A=
return 0;=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp___init__(TimeStamp *self, PyObject *args)=0A=
{=0A=
int y, mo, d, h=3D0, m=3D0;=0A=
double sec=3D0;=0A=
char *s;=0A=
unsigned int v;=0A=
=0A=
if (PyArg_ParseTuple(args, "s#", &s, &m))=0A=
{=0A=
if (m !=3D 8)=0A=
{=0A=
PyErr_SetString(ErrorObject, "8-character string expected");=0A=
return NULL;=0A=
}=0A=
memcpy(self->data, s, 8);=0A=
}=0A=
else=0A=
{=0A=
PyErr_Clear();=0A=
if (PyArg_ParseTuple(args, "iii|iid", &y, &mo, &d, &h, &m, =
&sec))=0A=
{=0A=
s=3Dself->data;=0A=
v=3D((((y-1900)*12+mo-1)*31+d-1)*24+h)*60+m;=0A=
s[0]=3Dv/16777216;=0A=
s[1]=3D(v%16777216)/65536;=0A=
s[2]=3D(v%65536)/256;=0A=
s[3]=3Dv%256;=0A=
sec /=3D sconv;=0A=
v=3D(unsigned int)sec;=0A=
s[4]=3Dv/16777216;=0A=
s[5]=3D(v%16777216)/65536;=0A=
s[6]=3D(v%65536)/256;=0A=
s[7]=3Dv%256;=0A=
}=0A=
else=0A=
{=0A=
return NULL;=0A=
}=0A=
}=0A=
Py_INCREF(Py_None);=0A=
return Py_None;=0A=
}=0A=
=0A=
static int TimeStamp_y, TimeStamp_m, TimeStamp_d, TimeStamp_mi;=0A=
=0A=
static void =0A=
TimeStamp_parts(TimeStamp *self)=0A=
{=0A=
unsigned long v;=0A=
=0A=
=
v=3Dself->data[0]*16777216+self->data[1]*65536+self->data[2]*256+self->d=
ata[3];=0A=
TimeStamp_y=3Dv/535680+1900;=0A=
TimeStamp_m=3D(v%535680)/44640+1;=0A=
TimeStamp_d=3D(v%44640)/1440+1;=0A=
TimeStamp_mi=3Dv%1440;=0A=
}=0A=
=0A=
static double=0A=
TimeStamp_sec(TimeStamp *self)=0A=
{=0A=
unsigned int v;=0A=
=0A=
=
v=3Dself->data[4]*16777216+self->data[5]*65536+self->data[6]*256+self->d=
ata[7];=0A=
return sconv*v;=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_year(TimeStamp *self, PyObject *args)=0A=
{=0A=
TimeStamp_parts(self);=0A=
return PyInt_FromLong(TimeStamp_y);=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_month(TimeStamp *self, PyObject *args)=0A=
{=0A=
TimeStamp_parts(self);=0A=
return PyInt_FromLong(TimeStamp_m);=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_day(TimeStamp *self, PyObject *args)=0A=
{=0A=
TimeStamp_parts(self);=0A=
return PyInt_FromLong(TimeStamp_d);=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_hour(TimeStamp *self, PyObject *args)=0A=
{=0A=
TimeStamp_parts(self);=0A=
return PyInt_FromLong(TimeStamp_mi/60);=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_minute(TimeStamp *self, PyObject *args)=0A=
{=0A=
TimeStamp_parts(self);=0A=
return PyInt_FromLong(TimeStamp_mi%60);=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_second(TimeStamp *self, PyObject *args)=0A=
{=0A=
return PyFloat_FromDouble(TimeStamp_sec(self));=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_timeTime(TimeStamp *self, PyObject *args)=0A=
{=0A=
TimeStamp_parts(self);=0A=
=0A=
return PyFloat_FromDouble(=0A=
TimeStamp_abst(TimeStamp_y, TimeStamp_m-1, TimeStamp_d-1, =
=0A=
TimeStamp_mi, 0)+=0A=
TimeStamp_sec(self)-gmoff=0A=
);=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_laterThan(TimeStamp *self, PyObject *args)=0A=
{=0A=
TimeStamp *o=3DNULL;=0A=
unsigned char *s;=0A=
PyObject *a;=0A=
int i;=0A=
=0A=
UNLESS(PyArg_ParseTuple(args, "O!", self->ob_type, &o)) return =
NULL;=0A=
=0A=
if (memcmp(self->data, o->data, 8) > 0)=0A=
{=0A=
Py_INCREF(self);=0A=
return OBJECT(self);=0A=
}=0A=
=0A=
self=3Do;=0A=
=0A=
UNLESS(a=3DPyString_FromStringAndSize(self->data, 8)) return NULL;=0A=
s=3D(unsigned char *)PyString_AsString(a);=0A=
=0A=
for (i=3D7; i > 3; i--) =0A=
{=0A=
if (s[i] =3D=3D 255) =0A=
s[i]=3D0;=0A=
else=0A=
{=0A=
s[i]++;=0A=
return PyObject_CallFunction(OBJECT(self->ob_type), "O", a);=0A=
}=0A=
}=0A=
=0A=
TimeStamp_parts(self);=0A=
if (TimeStamp_mi >=3D 1439) =0A=
{=0A=
TimeStamp_mi=3D0;=0A=
i =3D TimeStamp_y%4=3D=3D0 && (TimeStamp_y%100 !=3D 0 || =
TimeStamp_y%400=3D=3D0);=0A=
if (TimeStamp_d =3D=3D month_len[i][TimeStamp_m-1]) =0A=
{=0A=
TimeStamp_d=3D1;=0A=
if (TimeStamp_m =3D=3D 12)=0A=
{=0A=
TimeStamp_m=3D1;=0A=
TimeStamp_y++;=0A=
}=0A=
else=0A=
TimeStamp_m++;=0A=
}=0A=
else=0A=
TimeStamp_d++;=0A=
}=0A=
else=0A=
TimeStamp_mi++;=0A=
=0A=
return PyObject_CallFunction(OBJECT(self->ob_type), "iiiii", =0A=
TimeStamp_y, TimeStamp_m, TimeStamp_d,=0A=
TimeStamp_mi/60, TimeStamp_mi%60);=0A=
}=0A=
=0A=
static struct PyMethodDef TimeStamp_methods[] =3D {=0A=
{"year", (PyCFunction)TimeStamp_year, METH_VARARGS, ""},=0A=
{"minute", (PyCFunction)TimeStamp_minute, METH_VARARGS, ""},=0A=
{"month", (PyCFunction)TimeStamp_month, METH_VARARGS, ""},=0A=
{"day", (PyCFunction)TimeStamp_day, METH_VARARGS, ""},=0A=
{"hour", (PyCFunction)TimeStamp_hour, METH_VARARGS, ""},=0A=
{"second", (PyCFunction)TimeStamp_second, METH_VARARGS, ""},=0A=
{"seconds", (PyCFunction)TimeStamp_second, METH_VARARGS, ""},=0A=
{"timeTime", (PyCFunction)TimeStamp_timeTime, METH_VARARGS, ""},=0A=
{"laterThan", (PyCFunction)TimeStamp_laterThan, METH_VARARGS, ""},=0A=
#ifdef USE_EXTENSION_CLASS=0A=
{"__init__", (PyCFunction)TimeStamp___init__, METH_VARARGS, =0A=
""},=0A=
#endif =0A=
{NULL, NULL} /* sentinel */=0A=
};=0A=
=0A=
#ifndef USE_EXTENSION_CLASS=0A=
static TimeStampobject *=0A=
newTimeStamp(PyObject *ignored, PyObject *args)=0A=
{=0A=
TimeStamp *self;=0A=
=0A=
UNLESS(self =3D PyObject_NEW(TimeStamp, &TimeStampType)) return =
NULL;=0A=
=0A=
ignored=3D__init__(self, args);=0A=
if (! ignored) return NULL;=0A=
=0A=
Py_DECREF(ignored);=0A=
return self;=0A=
}=0A=
#endif=0A=
=0A=
static void=0A=
TimeStamp_dealloc(TimeStamp *self)=0A=
{=0A=
#ifdef USE_EXTENSION_CLASS=0A=
Py_DECREF(self->ob_type);=0A=
#endif =0A=
PyMem_DEL(self);=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_repr(TimeStamp *self)=0A=
{=0A=
return PyString_FromStringAndSize(self->data, 8);=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_str(TimeStamp *self)=0A=
{=0A=
char buf[128];=0A=
int l;=0A=
=0A=
TimeStamp_parts(self);=0A=
l=3Dsprintf(buf, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%lf",=0A=
TimeStamp_y, TimeStamp_m, TimeStamp_d, =0A=
TimeStamp_mi/60, TimeStamp_mi%60, TimeStamp_sec(self));=0A=
=0A=
return PyString_FromStringAndSize(buf, l);=0A=
}=0A=
=0A=
static int=0A=
TimeStamp_compare(TimeStamp *v, TimeStamp *w)=0A=
{=0A=
return memcmp(v->data, w->data, 8);=0A=
}=0A=
=0A=
static long=0A=
TimeStamp_hash(TimeStamp *self)=0A=
{=0A=
return self->data[0]+self->data[1]+self->data[2]+self->data[3]=0A=
+self->data[4]+self->data[5]+self->data[6]+self->data[7];=0A=
}=0A=
=0A=
static PyObject *=0A=
TimeStamp_getattro(TimeStamp *self, PyObject *name)=0A=
{=0A=
#ifndef USE_EXTENSION_CLASS=0A=
char *s;=0A=
=0A=
if (! (s=3DPyString_AsString(name))) return NULL;=0A=
return Py_FindMethod(TimeStamp_methods, self, s); =0A=
#else=0A=
return Py_FindAttr(OBJECT(self), name);=0A=
#endif=0A=
}=0A=
=0A=
#ifdef USE_EXTENSION_CLASS=0A=
static PyExtensionClass=0A=
#else=0A=
static PyTypeObject =0A=
#endif=0A=
TimeStampType =3D {=0A=
PyObject_HEAD_INIT(NULL)=0A=
0, /*ob_size*/=0A=
"TimeStamp", /*tp_name*/=0A=
sizeof(TimeStamp), /*tp_basicsize*/=0A=
0, /*tp_itemsize*/=0A=
/* methods */=0A=
(destructor)TimeStamp_dealloc, /*tp_dealloc*/=0A=
(printfunc)0, /*tp_print*/=0A=
(getattrfunc)0, /*obsolete tp_getattr*/=0A=
(setattrfunc)0, /*obsolete tp_setattr*/=0A=
(cmpfunc)TimeStamp_compare, /*tp_compare*/=0A=
(reprfunc)TimeStamp_repr, /*tp_repr*/=0A=
0, /*tp_as_number*/=0A=
0, /*tp_as_sequence*/=0A=
0, /*tp_as_mapping*/=0A=
(hashfunc)TimeStamp_hash, /*tp_hash*/=0A=
(ternaryfunc)0, /*tp_call*/=0A=
(reprfunc)TimeStamp_str, /*tp_str*/=0A=
(getattrofunc)TimeStamp_getattro,=0A=
(setattrofunc)0,=0A=
=0A=
/* Space for future expansion */=0A=
0L,0L,=0A=
"Simple time stamps"=0A=
#ifdef USE_EXTENSION_CLASS=0A=
, METHOD_CHAIN(TimeStamp_methods),=0A=
#endif=0A=
};=0A=
=0A=
static struct PyMethodDef Module_Level__methods[] =3D {=0A=
#ifndef USE_EXTENSION_CLASS=0A=
{"TimeStamp", (PyCFunction)newTimeStamp, METH_VARARGS, ""},=0A=
#endif=0A=
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */=0A=
};=0A=
=0A=
void=0A=
initTimeStamp()=0A=
{=0A=
PyObject *m, *d;=0A=
char *rev=3D"$Revision: 1.6 $";=0A=
=0A=
if (TimeStamp_init_gmoff() < 0) return;=0A=
if (! ExtensionClassImported) return;=0A=
=0A=
/* Create the module and add the functions */=0A=
m =3D Py_InitModule4("TimeStamp", Module_Level__methods,=0A=
"Simple time stamps",=0A=
(PyObject*)NULL,PYTHON_API_VERSION);=0A=
=0A=
/* Add some symbolic constants to the module */=0A=
d =3D PyModule_GetDict(m);=0A=
=0A=
#ifndef USE_EXTENSION_CLASS=0A=
TimeStampType.ob_type=3D&PyType_Type;=0A=
#else=0A=
PyExtensionClass_Export(d, "TimeStamp", TimeStampType);=0A=
#endif=0A=
=0A=
PyDict_SetItemString(d,"TimeStampType", OBJECT(&TimeStampType));=0A=
=0A=
ErrorObject =3D PyString_FromString("TimeStamp.error");=0A=
PyDict_SetItemString(d, "error", ErrorObject);=0A=
=0A=
PyDict_SetItemString(d, "__version__",=0A=
PyString_FromStringAndSize(rev+11,strlen(rev+11)-2));=0A=
=0A=
/* Check for errors */=0A=
if (PyErr_Occurred())=0A=
Py_FatalError("can't initialize module TimeStamp");=0A=
}=0A=
------ =_NextPart_000_01BF8865.178AFB40--