on off time behavior in CQ/AEM

On off time feature in CQ is mainly used if you want pages to be available after specific time and at same time don't want to activate bunch of pages at same time. For example you have 1K pages and you want to make those pages available at 9:00AM next day, But you know that you have high traffic on author at 9:00AM so it won't be good idea to activate all 1K pages at that time using scheduled activation. So what you can do is, set on time for those pages at 9:00AM next day and then activate those pages during less traffic time (Even before 9:00AM). Pages will go to publish but it won't be rendered as on time is not reached yet. 

PageModification event the On/Offtime reached trigger are only part of the on/off time functionality. When you set the on or off time of a page you are scheduling it for publication (there is a scheduled activation/deactivation function which is different than on/off time). With on/off time you set the value and then you replicate the page to the publish server immediately.
One of the CQ filters (I am not sure which one) is responsible for checking the on/off time whenever a page is requested. If current time is either before the on time or after the off time the system returns a 404 for the page as if it were not present, even though content of the page is still in the publish repository. The of/off time does not change the repository, it controls whether or not the page will be accessible. All of this logic occurs on the publish server - not the author server.
The PageModification event and the on/off time trigger are used to trigger a dispatcher flush event when there on/off time occurs in order ensure that the page and anything that references it are flushed from cache and thereby regenerated based on the new availability.
This is different than the scheduled activation/deactivation process. When you schedule a page of activation/deactivation an OSGI event is created for the time specified. When the time specified is reached the OSGI event system fires an notification which causes a Job Handler to get called. This job handler then does the required activation/deactivation just as if a person had pushed the activate button. This logic occurs on the author server.
There are several subtle impacts to the on/off time system to be aware of:
  • Because the on/off time functionality is part of the CQ application and not part of Sling or CRX you can still access the content in the repository if the page is not accessible due to on/off time. So if you have code that uses the pure sling or JCR APIs to access content you will want to consider whether or not you need add a filter to you code to prevent pulling up content which is before/after its on/off time. If you are using CQ APIs (like the page manager) to get a page you need to make sure you use a PageFilter (https://dev.day.com/docs/en/cq/current/javadoc/index.html?com/day/cq/w cm/api/PageFilter.html) that respects the on/off time to ensure you don't access invalid content.
  • You can not use the on time to schedule updates to a page. All the on time does is control whether or not the page as a whole is available. So if you have an existing page and you change you can not use the on time to schedule that change's publication. If you were to edit the page and set the on time to 2 days from now and publish the page it would immediately become unavailable until the on time had passed. If you didn't activate it the on time would cause the page as a whole to be activated. You need to use scheduled activation functionality to schedule activation of updates.
  • Make sure that trigger for on/off time reached is set in replication agent, so that replication agent replicate content when on/off time is reached.
Using API http://dev.day.com/docs/en/cq/current/javadoc/com/day/cq/wcm/api/Page.html you can get on and off time for the page.

This property in replication agent checks if config for on off trigger is active http://dev.day.com/docs/en/cq/current/javadoc/com/day/cq/replication/AgentConfig.html#isTriggeredOnOffTime%28%29

To get on off time using query

final String now = session.getValueFactory().createValue(Calendar.getInstance()).getString();

final Query q = session.getWorkspace().getQueryManager().createQuery( "/jcr:root/content//*[@offTime > xs:dateTime('" + now + "') or @onTime > xs:dateTime('" + now + "')]",  Query.XPATH);

final QueryResult r = q.execute();

 final NodeIterator iter = r.getNodes();

while (iter.hasNext()) {

                    final Node node = iter.nextNode();

                    final long onTime = node.hasProperty(NameConstants.PN_ON_TIME) ? node.getProperty(NameConstants.PN_ON_TIME).getLong(): 0;

                    final long offTime = node.hasProperty(NameConstants.PN_OFF_TIME) ? node.getProperty(NameConstants.PN_OFF_TIME).getLong(): 0;