How to set effective date in dexterity

Hope someone can enlighten me on how set effective and expires dates.

The content has this behaviors
plone.app.dexterity.behaviors.metadata.IPublication

After published, I need to set expiration date to 3 days later. What is the right way to set the expires date?

obj.setEffectiveDate(DateTime(2020, 1, 3, 18, 0))
obj.setExpirationDate(DateTime(2020, 1, 6, 18, 0))

or

obj.effective_date = DateTime(2020, 1, 3, 18, 0)
obj.expiration_date = DateTime(2020, 1, 6, 18, 0)

or

obj.effective = datetime(2020, 1, 3, 18, 0)
obj.expires = datetime(2020, 1, 6, 18, 0)

then
obj.reindexObject()

Thanks in advance

I think it should be set via Adapter with a datetime Object

mydatetime = datetime.now()
publication = IPublication(obj, None)    
if publication is not None:        
    publication.expires = mydatetime
    publication.effective = mydatetime
4 Likes

I also do this way in my code. It is important to re-index the object after, as mentioned in the original post's code:

obj.reindexObject()

It's better to reindex only indexes that you need (for performance reasons and to avoid touching other indexes like modified date), so:

obj.reindexObject(idxs=['effective', 'expires'])
2 Likes

I don't think anyone answered the question:

May I suggest @1letter approach and:

obj.effective = datetime(2020, 2, 28, 18, 0) #Feb 28 2020
obj.expires = obj.effective + timedelta(days=3) #March 2 2020

I have tried this but this will cause other problems, e.g
plone.app.layout.viewlets.content.isExpired

    if base_hasattr(self.context, 'expires'):
        return self.context.expires().isPast()

will fail.
And don't know about the indexing side effects.

have tried this but this will cause other problems, e.g
plone.app.layout.viewlets.content.isExpired

    if base_hasattr(self.context, 'expires'):
    return self.context.expires().isPast()

will fail.

My guess that is fails is because timedelta is part of datetime in the Python standard library and effective, expired etc. all need to be Zope DateTime's. (camel case). See this chapter in the Plone documentation at https://docs.plone.org/develop/plone/misc/datetime.html for more information.

If you want to use timedelta you will have to convert the DateTime to datetime, add the timedelta and then convert back to DateTime. :frowning:

1 Like

The IPublication interface works only with datetime (Python standard library module) types. This is one of the reasons I recommend dealing with effective and expiration dates only through this interface, and forget about the other methods.

This should work:

from datetime import datetime
from datetime import timedelta

mydatetime = datetime.now()
publication = IPublication(obj, None)    
if publication is not None:        
    publication.expires = mydatetime
    publication.effective = mydatetime + timedelta(days=3)
    obj.reindexObject()  

As pointed by @cekk you can pass the parameter idxs to reindexObject() in order to restrict which indexes will be affected. Do this if performance is important. I recommend checking in portal_catalog through ZMI to see which indexes may be relevant. I think there were changes in this area in the latest Plone versions.

1 Like

for the sake of completeness, that's my import code for manipulate all relevant dates

"""
Example JSON with relevant timestamps of object
{
  ...
  "created": "2013-08-28T09:29:29+00:00", 
  "effective": "2013-08-28T11:30:00",
  "modified": "2015-12-11T11:48:14+00:00",
  "expires": null
  ...
}

data... is the json dictionary
obj... is the DexterityObject after creation
"""

publication   = IPublication(obj, None)
effective     = data.get('effective', None)
expires       = data.get('expires', None)
created       = data.get('created', None)
modified      = data.get('modified', None)

if publication is not None:
  if effective:
    publication.effective = datetime.strptime(effective, "%Y-%m-%dT%H:%M:%S")
    obj.reindexObject(idxs=['effective'])
    
  if expires:
    publication.expires = datetime.strptime(expires, "%Y-%m-%dT%H:%M:%S")
    obj.reindexObject(idxs=['expires'])
  
if created:
  obj.creation_date = DateTime(datetime.strptime(created, "%Y-%m-%dT%H:%M:%S%z"))
  obj.reindexObject(idxs=['created'])
    
if modified:
  obj.modification_date = DateTime(datetime.strptime(modified, "%Y-%m-%dT%H:%M:%S%z"))
  obj.reindexObject(idxs=['modified'])
2 Likes