Modern Events Calendar Lite was closed on wordpress.org on May 11, 2022, permanently, for a guideline violation (that's what its plugin page still says). Plenty of sites still run it, updated from the developer's own site. Whether you're moving to something else or just want your events out, it helps to know how MEC stores them, because a few of its choices will quietly give you the wrong dates if you copy fields as they look.
I read all of this from MEC Lite 6.5.6, the last version on wordpress.org, mostly from the function that saves an event. Newer builds still have to read events saved by older ones, so the stored format should be the same, but check your own data with the queries below before you trust any of it.
Where your events live
- Each event is a post of type
mec-events: title, content, excerpt, featured image. - The schedule is in post meta:
-
mec_start_date/mec_end_date(Y-m-d) -
mec_start_day_seconds/mec_end_day_seconds(seconds after midnight) mec_allday-
mec_timezone("global" means the site's timezone) - the repeat settings in
mec_repeat_*
-
- There are two tables,
wp_mec_eventsandwp_mec_dates. MEC fills them from the meta when an event is saved and uses them for its calendar queries. Read the meta; treat the tables as derived. - Venues, organizers and categories are taxonomies:
-
mec_location:address,latitudeandlongitudein term meta. -
mec_organizer:tel,emailandurlin term meta. -
mec_category: the colour is inmec_cat_color.
-
- Bookings, if you used them, are separate:
mec-booksposts plus awp_mec_bookingstable.
To see which repeat types you actually have (and so which of the traps below apply to you):
SELECT pm.meta_value AS repeat_type, COUNT(*) AS events
FROM wp_postmeta pm
JOIN wp_posts p ON p.ID = pm.post_id
WHERE pm.meta_key = 'mec_repeat_type'
AND p.post_type = 'mec-events'
AND p.post_status NOT IN ('trash', 'auto-draft')
GROUP BY pm.meta_value;
An empty repeat_type means the event doesn't repeat.
The traps
1. Weekly intervals are stored in days. "Every 2 weeks" is saved as mec_repeat_interval = 14. MEC multiplies the week count by 7 before saving. Copy it straight into an RRULE and you get INTERVAL=14, which is every fourteen weeks.
2. "Ends after N times" is stored as N − 1. mec_repeat_end_at_occurrences holds one less than what the user typed. Six classes becomes 5 in the database.
$type = get_post_meta( $id, 'mec_repeat_type', true );
$interval = max( 1, (int) get_post_meta( $id, 'mec_repeat_interval', true ) );
if ( 'weekly' === $type ) {
$interval = max( 1, intdiv( $interval, 7 ) );
}
$count = null;
if ( 'occurrences' === get_post_meta( $id, 'mec_repeat_end', true ) ) {
$count = (int) get_post_meta( $id, 'mec_repeat_end_at_occurrences', true ) + 1;
}
3. Weekday numbers are ISO. mec_certain_weekdays uses 1 = Monday through 7 = Sunday, not the 0 = Sunday you'd get from PHP's w or JavaScript. The "weekday" and "weekend" repeat types don't store their days on the event at all. They come from MEC's settings (mec_options → settings → weekdays / weekends), which default to 1–5 and 6–7.
4. "Advanced" repeats are little tokens. mec_advanced_days holds values like Sun.1 (first Sunday of the month) or Fri.l (last Friday). That's a monthly rule by position, BYDAY=1SU or BYDAY=-1FR. One event can hold several tokens, so check for that before you assume one rule per event.
5. Location or organizer ID 1 means "hide it". It isn't a venue. If you import it as one you'll end up with a venue called whatever term 1 is on your site.
6. Times are stored three ways. There are 12-hour fields (mec_start_time_hour, _minutes, _ampm), a seconds-after-midnight field, and a datetime string. On sites set to 24-hour time MEC converts the hour back to 12-hour before saving it. Use mec_start_day_seconds / mec_end_day_seconds and skip the hour fields.
7. Extra and skipped days. Skipped dates are a comma list in mec_not_in_days. The "custom days" repeat type keeps its own list in mec_in_days as start:end pairs (2026-10-17:2026-10-17), sometimes with times appended as hh-mm-AM. There's no rule behind those, just the list.
8. Your URLs may not be the defaults. Single events live at /events/<slug>/ and categories at /mec-category/<slug>/ unless someone changed them under MEC's settings (slug and category_slug in the same mec_options array). Read those two values before you switch, or your redirects will only cover URLs your site never used.
Before you switch
- Run the query above and note which repeat types you have.
- Spot-check one weekly event and one "ends after N times" event by hand against MEC's own calendar.
- Write down your two URL slugs.
- Decide what happens to bookings. They're in their own post type and table, not on the events.
- Keep MEC installed but deactivated until you've compared a month of dates side by side.
Disclosure
I build Beacon Events, a free events calendar on wordpress.org, and version 0.10.1 has an importer for exactly this: https://wordpress.org/plugins/beacon-events/ . It handles the traps above, keeps venues with their addresses, organizers, category colours, images and timezones, and redirects old event and category links, custom slugs included, once MEC is off. What it doesn't do: a "custom days" list comes in as its first date, an advanced rule with several weekdays keeps the first one, and MEC bookings aren't imported. The report after the import lists the events that hit one of those.
Top comments (0)