Honor timezone of the acting library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Summary +++++++ * Display day-granular due dates in the circulating library's timezone. * Only display the date portion of the due date for day-granular circulations. * Display the full timestamp, in the client's timezone rather than the circulation library's, for hourly circulations. * Provide infrastructure for more advanced formatting of timestamps. * Override the built-in AngularJS date filter with an implementation that uses moment.js, providing consistency and better standards compliance. Upgrade note ++++++++++++ The following query will adjust all historical, unaged circulations so that if their due date field is pushed to the end of the day, it is done in the circulating library's time zone, and not the server time zone. It is safe to run this after any change to library time zones. Running this is not required, as no code before this change has depended on the time string of '23:59:59'. It is also not necessary if all of your libraries are in the same time zone, and that time zone is the same as the database's configured time zone. [source,sql] ---- DO $$ declare new_tz text; ou_id int; begin for ou_id in select id from actor.org_unit loop for new_tz in select oils_json_to_text(value) from actor.org_unit_ancestor_setting('lib.timezone',ou_id) loop if new_tz is not null then update action.circulation set due_date = (due_date::timestamp || ' ' || new_tz)::timestamptz where circ_lib = ou_id and substring((due_date at time zone new_tz)::time::text from 1 for 8) <> '23:59:59'; end if; end loop; end loop; end; $$; ---- Details +++++++ This is a followup to the work done in bug 1485374, where we added the ability for the client to specify a timezone in which timestamps should be interpreted in business logic and the database. Most specifically, this work focuses on circulation due dates and the closed date editor. Due dates, where displayed using stock templates (including receipt templates) and used for fine calculation, are now manipulated in the library's configured timezone. This is controlled by the new 'lib.timezone' YAOUS, loaded from the server when required. Additionally, closings are recorded in the library's timezone so that so that due date calculation is more accurate. The closed date editor is also taught how to display closings in the closed library's timezone. Closed date entries also explicitly record if they are a full day closing, or a multi-day closing. This significantly simplifies the editor, and may be useful in other contexts. To accomplish this, we use the moment.js library and the moment-timezone addon. This is necessary because the stock AngularJS date filter does not understand locale-aware timezone values, which are required to support DST. A simple mapper translates the differences in format values from AngularJS date to moment.js. Of special note are a set of new filters used for formatting timestamps under certain circumstances. The new egOrgDateInContext, egOrgDate, and egDueDate filters provide the functionality, and autogrid is enhanced to make use of these where applicable. egGrid and egGridField are also taught to accept default and field-specific options for applying date filters. These filters may be useful in other or related contexts. The egDueDate filter, used for all existing displays of due date via Angular code, intentionally interprets timestamps in two different ways WRT timezone, based on the circulation duration. If the duration is day-granular (that is, the number of seconds in the duration is divisible by 86,400, or 24 hours worth of seconds) then the date is interpreted as being in the circulation library's timezone. If it is an hourly loan (any duration that does not meet the day-granular criterium) then it is instead displayed in the client's timezone, just as all other timestamps currently are, because of the work in 1485374. The OPAC is adjusted to always display the due date in the circulating library's timezone. Because the OPAC displays only the date portion of the due date field, this difference is currently considered acceptable. If this proves to be a problem in the future, a minor adjustment can be made to match the egDueDate filter logic. Now that due dates are globally stored in the configured timezone of the circulating library, the automatic adjustment to day-granular due dates needs to take those timezones into account. An optional SQL command is provided by the upgrade script to retroactively adjust existing due dates after library configuration is complete. This work, as with 1485374, was funded by SITKA, and we thank them for their partnership in making this happen!