DEV Community

Jeffrey Inman
Jeffrey Inman

Posted on

Moving off EventON: its timestamps aren't what they look like

EventON is a popular WordPress events calendar, sold on CodeCanyon, with a free Lite version on wordpress.org. If you're moving off it, or just exporting your events, there's one thing to understand before anything else: the start and end times look like normal unix timestamps, and they aren't. Convert them the obvious way and every event moves by your site's UTC offset.

I read this from EventON Lite 2.5.9, mostly from the function that turns the date fields on the edit screen into stored values. As far as I can tell the paid version uses the same post type and fields, but check a few of your own events against what's below.

Where your events live

  • Each event is a post of type ajde_events.
  • The times are in evcal_srow (start) and evcal_erow (end), as unix timestamps.
  • The event's timezone is in _evo_tz. All-day events have evcal_allday = "yes".
  • Repeats are in evcal_repeat, evcal_rep_freq, evcal_rep_gap and a few more fields, plus a list called repeat_intervals.
  • Locations and organizers are the event_location and event_organizer taxonomies.
  • Event types are event_type, and extra type sets become event_type_2, event_type_3 and so on.
  • The event colour is evcal_event_color, stored as hex without the #.
  • Status is _status: scheduled, cancelled, rescheduled, postponed, movedonline, tentative or preliminary. The online link is in _vir_url.

Trap 1: the timestamps are "virtual"

When you save an event for 6:30 pm, EventON builds the timestamp in UTC from the wall-clock time you typed. So evcal_srow is 18:30 UTC, whatever your timezone is. It's the local time pretending to be UTC.

That means this is wrong on any site that isn't on UTC:

// Wrong: shifts the event by the site's offset.
$start = wp_date( 'Y-m-d H:i', (int) get_post_meta( $id, 'evcal_srow', true ) );
Enter fullscreen mode Exit fullscreen mode

and this is right:

// The stored number is wall-clock time encoded as UTC, so read it back as UTC.
$start = gmdate( 'Y-m-d H:i', (int) get_post_meta( $id, 'evcal_srow', true ) );
$zone  = get_post_meta( $id, '_evo_tz', true ) ?: wp_timezone_string();
Enter fullscreen mode Exit fullscreen mode

The same goes for SQL. FROM_UNIXTIME() converts with the session's time zone, so set it to UTC first or you get the shift there too:

SET time_zone = '+00:00';
SELECT p.ID, p.post_title, FROM_UNIXTIME(pm.meta_value) AS starts_local
FROM wp_posts p
JOIN wp_postmeta pm ON pm.post_id = p.ID AND pm.meta_key = 'evcal_srow'
WHERE p.post_type = 'ajde_events'
  AND p.post_status NOT IN ('trash', 'auto-draft')
ORDER BY pm.meta_value;
Enter fullscreen mode Exit fullscreen mode

Trap 2: trust repeat_intervals, not the settings

A repeating event stores its settings:

  • how often: evcal_rep_freq = hourly, daily, weekly, monthly, yearly or custom
  • the gap
  • for weekly, the chosen days in evo_rep_WKwk (0 = Sunday)
  • for monthly, "by weekday" in evo_rep_WK with the week of the month in evo_repeat_wom

It also stores repeat_intervals: every occurrence it generated, as [start, end] pairs of the same virtual timestamps. That list is what the calendar actually shows.

Rebuilding a rule from the settings mostly works, but not always. Custom repeats are only a list, and hourly repeats don't map to most calendar formats. If you rebuild a rule, expand it and compare the dates against repeat_intervals before you trust it. When they don't match, the list is the truth.

Trap 3: location details aren't in term meta

Location and organizer details (address, coordinates, contact) aren't in wp_termmeta. They're in one big serialized option, evo_tax_meta, keyed by taxonomy and term ID:

$meta    = get_option( 'evo_tax_meta', array() );
$address = $meta['event_location'][ $term_id ]['location_address'] ?? '';
Enter fullscreen mode Exit fullscreen mode

Older sites may also have a per-term option named taxonomy_<term id>, which EventON reads as a fallback. Check both.

Trap 4: types come in numbered sets

event_type is the first set of labels; turning on more creates event_type_2, event_type_3, each with its own URL (/event-type_2/<slug>/). Decide where each set goes, and redirect all of them.

URLs

Single events default to /events/<slug>/ (changeable in EventON's settings). Taxonomy pages are /event-location/<slug>/, /event-organizer/<slug>/ and /event-type/<slug>/, and each extra type set gets its own base. Note what yours are before you switch.

Before you switch

  • Convert one event by hand with gmdate() and compare it with what EventON shows on the front end.
  • Count repeating events and compare each rebuilt rule with repeat_intervals.
  • Export evo_tax_meta along with your posts, or your venues lose their addresses.
  • List every event_type* taxonomy and its URL base.

Disclosure

I build Beacon Events, a free events calendar on wordpress.org. Version 0.12.0 imports from EventON and EventON Lite and handles all four traps: https://wordpress.org/plugins/beacon-events/ . It reads the virtual timestamps correctly, keeps a repeat rule only when it reproduces EventON's stored dates exactly, pulls addresses from evo_tax_meta, turns every type set into categories, and redirects the old location, organizer, type and event links. Custom date lists and hourly repeats come across as their first date, and the import report lists those events so you can check them.

Top comments (0)