WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Conversation

@infowprobo
Copy link

What?

Adds ai/calculate-dates ability to calculate dates from natural language patterns.

Closes #55

This PR implements a date calculation ability that helps AI assistants accurately calculate recurring dates from natural language patterns like "3rd Tuesday of each month" or "every other Friday".

Why?

As noted in #55, AI models struggle with date calculations, especially recurring patterns. This ability provides:

  • Accurate date calculation for AI-powered features
  • Reusable across different WordPress applications
  • Handles edge cases like leap years and month-end dates
  • Consistent date calculation logic

How?

Implementation:

  • Created Date_Calculation class in includes/Abilities/Utilities/
  • Registered as ai/calculate-dates ability
  • Uses WordPress Abilities API
  • REST API enabled via show_in_rest => true
  • Follows existing ability patterns (similar to Posts class)

Architecture:

  • Uses native PHP DateTime class (no external dependencies)
  • Respects WordPress timezone settings
  • Input validation via schema
  • Permission check: requires edit_posts capability
  • Limits occurrences to 52 maximum (prevents abuse)

Supported Patterns

  1. Relative patterns: tomorrow, next Monday, in 3 days
  2. Nth weekday patterns: 3rd Tuesday, first Friday, last Monday
  3. Recurring patterns: every Monday, every other Tuesday
  4. Interval patterns: every 2 weeks, every month, every 3 days

Testing Instructions

Via WP-CLI

wp shell
$ability = wp_get_ability('ai/calculate-dates');

// Test tomorrow
$result = $ability->execute(array('pattern' => 'tomorrow'));
print_r($result);

// Test 3rd Tuesday
$result = $ability->execute(array(
    'pattern' => '3rd tuesday',
    'occurrences' => 3
));
print_r($result);

// Test every Monday
$result = $ability->execute(array(
    'pattern' => 'every monday',
    'occurrences' => 5
));
print_r($result);


Expected Results

Input:

{
  "pattern": "every monday",
  "occurrences": 3
}

Output:

{
  "dates": [
    "2025-12-01T00:00:00+00:00",
    "2025-12-08T00:00:00+00:00",
    "2025-12-15T00:00:00+00:00"
  ],
  "pattern": "every monday"
}

OR

wp eval "$ability = wp_get_ability('ai/calculate-dates'); print_r($ability->execute(array('pattern' => 'every monday', 'occurrences' => 5)));"

AliShanScreenshot 2025-11-30 at 11  35 06

Testing Instructions for Keyboard

N/A - This PR does not affect the user interface. It only adds backend ability for date calculations.

Screenshots or screencast

N/A - Backend ability with no visual output. The ability is accessible via PHP, WP-CLI, and REST API.

Testing Checklist

  • Tested locally via WP-CLI
  • All pattern types working correctly
  • Error handling working (invalid patterns return WP_Error)
  • Permission checks working
  • Input validation working
  • Timezone handling working
  • Occurrences limit enforced
  • PHPUnit tests (TODO)

Code Quality

  • Follows WordPress Coding Standards
  • All strings are translatable
  • Proper PHPDoc comments
  • Uses sanitization callbacks
  • Error handling with WP_Error
  • Follows existing ability patterns in the repo

Notes

  • Uses same registration pattern as Posts ability
  • Registered in bootstrap.php alongside other utilities
  • No external dependencies
  • Works with any timezone
  • Future enhancement: Add more complex patterns (e.g., "3 weeks from Friday")

- Triggers on release publish
- Reuses existing build-plugin-zip workflow
- Downloads built artifact
- Uploads ai.zip as release asset

Fixes WordPress#109
- Implements ai/calculate-dates ability as requested in WordPress#55
- Supports relative patterns (tomorrow, next Monday, in 3 days)
- Supports nth weekday patterns (3rd Tuesday, first Friday, last Monday)
- Supports recurring patterns (every Monday, every other Tuesday)
- Supports interval patterns (every 2 weeks, every month)
- Uses native PHP DateTime (no external dependencies)
- Includes input validation and error handling
- REST API enabled
- Limits occurrences to 52 maximum
- Requires edit_posts capability

Addresses WordPress#55
@github-actions
Copy link

github-actions bot commented Nov 30, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @alishanvr, @jmarx.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: alishanvr, jmarx.

Co-authored-by: mindctrl <[email protected]>
Co-authored-by: dkotter <[email protected]>
Co-authored-by: infowprobo <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@codecov
Copy link

codecov bot commented Nov 30, 2025

Codecov Report

❌ Patch coverage is 0% with 195 lines in your changes missing coverage. Please review.
✅ Project coverage is 32.56%. Comparing base (36c5b34) to head (8f2687a).
⚠️ Report is 92 commits behind head on develop.

Files with missing lines Patch % Lines
includes/Abilities/Utilities/Date_Calculation.php 0.00% 195 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             develop     #116      +/-   ##
=============================================
+ Coverage      29.37%   32.56%   +3.18%     
- Complexity       145      215      +70     
=============================================
  Files             14       17       +3     
  Lines            885     1207     +322     
=============================================
+ Hits             260      393     +133     
- Misses           625      814     +189     
Flag Coverage Δ
unit 32.56% <0.00%> (+3.18%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jeffpaul jeffpaul requested a review from dkotter December 1, 2025 03:29
@jeffpaul jeffpaul added this to the Future Release milestone Dec 1, 2025
* @return bool True if pattern is relative.
*/
private function is_relative_pattern( string $pattern ): bool {
return (bool) preg_match( '/^(tomorrow|yesterday|today|next\s+\w+day|in\s+\d+\s+(day|week|month|year)s?)$/i', $pattern );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious how this, and related methods, might work with non-English languages?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should pattern keywords also be translatable (e.g., users can type "demain" instead of "tomorrow"), or just the UI strings?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, don't think this type of pattern matching will work for any languages outside of english. Ideally we find a better way to do this

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't see your comment while I was leaving mine but ideally we find an approach that will work irregardless of the language. I'm not sure off the top of my head the best way to do that but having hardcoded strings here will prevent that from working

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After thinking about this more, what if we move away from natural language parsing entirely and use a structured input format instead?

Current (language-dependent):

{
  "pattern": "3rd Tuesday"
}

Proposed (language-neutral):

{
  "type": "nth_weekday",
  "weekday": 2,  // 0=Sunday, 1=Monday, 2=Tuesday...
  "nth": 3
}

===

Some Examples:

Every Monday:

{
  "type": "recurring",
  "weekday": 1,
  "interval": 1
}

First Friday

{
  "type": "nth_weekday",
  "weekday": 5,
  "nth": 1
}

Every 2 weeks

{
  "type": "interval",
  "unit": "week",
  "amount": 2
}

What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming this file wasn't meant to be part of this PR?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's related to #109

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally this PR stays focused on just the needed changes and doesn't include code from #109

Copy link
Author

@infowprobo infowprobo Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, that file shouldn't be here! It was from #109 and got included accidentally. I've removed it now in d63ba54

/**
* Date calculation utility WordPress Abilities.
*
* @since 0.2.0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can update all @since statements to x.x.x and these will be updated during release

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will use x.x.x

I will update it by the end of this week.
is this ok? Or you need it more urgent?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is fine, no rush on my end

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in cf1c7c0

'execute_callback' => array( $this, 'execute_calculate_dates' ),
'permission_callback' => array( $this, 'permission_callback' ),
'meta' => array(
'show_in_rest' => true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be surfaced in the REST API? Seems like surfacing this via MCP would suffice

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not sure. So, I added to show in rest as well.
If we don't need to show in rest then I will remove it. Please confirm!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now I would leave this argument off

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the show_in_rest in 5f7681b

*/
public function execute_calculate_dates( array $input ) {
// Validate pattern is provided.
if ( empty( $input['pattern'] ) ) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is set as required in our schema, no need for the extra check here I don't think

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, i will fix this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 78a870a

*/
public function permission_callback( array $args ) {
// Anyone who can edit posts can use date calculations.
if ( ! current_user_can( 'edit_posts' ) ) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the thought process behind this permission check? It doesn't seem like we're interacting with any WordPress data so could argue no need for a capability check and maybe fine with just a user logged in check

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! My thinking was to require some minimum capability to prevent anonymous users from making potentially resource-intensive date calculations.

However, I agree - since we're not reading/writing WordPress data, just doing date math, a logged-in check would be sufficient.

Should I change it to:

public function permission_callback( array $args ) {
    return is_user_logged_in();
}

Or remove the permission check entirely and allow public access?

Let me know your preference!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could see a case to make for keeping this open to everyone but for now, probably safer to have the is_user_logged_in check

Copy link
Author

@infowprobo infowprobo Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed/Updated in 8f2687a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add date calculation ability

5 participants