[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--