This prompt is for calendar integration engineers and scheduling platform developers who need to convert natural language recurrence descriptions into structured, machine-readable rules. The core job is to take a user-facing string like 'every other Tuesday until the end of the year' and produce a standards-compliant RRULE (RFC 5545), a human-readable confirmation, and a flag for any unsupported patterns. This is a normalization task, not a scheduling engine. The prompt assumes the input is a single recurrence description and the output is a single structured object ready for ingestion into a calendar system or event store.
Prompt
Recurring Event Rule Normalization Prompt Template

When to Use This Prompt
Define the job, reader, and constraints for the Recurring Event Rule Normalization Prompt Template.
Use this prompt when you have a reliable natural language input and need a deterministic, validatable output. It is designed for a backend processing pipeline where a user's free-text rule is passed to an LLM before being stored in a database or sent to a calendar API. The prompt includes explicit instructions to validate against RFC 5545, which means it is suitable for systems that must interoperate with standard calendar clients (Google Calendar, Outlook, iCal). Do not use this prompt for generating event instances (expansion), resolving conflicts, or handling complex exception dates. Those are separate scheduling problems that belong in application code, not in a normalization prompt.
Before integrating this prompt, ensure you have a clear contract for what your system considers 'unsupported.' The prompt includes a flag for patterns it cannot normalize, but you must define the boundary. For example, 'every payday' or 'whenever the moon is full' should be flagged, not hallucinated. The next step after reading this playbook is to copy the template, define your [UNSUPPORTED_PATTERNS] list, and run it against a golden test set of 50+ recurrence descriptions that include edge cases like leap year rules, monthly-by-day patterns, and interval limits.
Use Case Fit
Where the Recurring Event Rule Normalization Prompt works, where it breaks, and what you must have in place before relying on it.
Strong Fit: Calendar Integration Pipelines
Use when: ingesting user-facing natural language recurrence descriptions (e.g., 'every other Tuesday', 'monthly on the 15th') into calendar systems that require RFC 5545 RRULE strings. Guardrail: always validate the generated RRULE against an RFC 5545 parser before storing; reject rules that fail to parse rather than silently corrupting the calendar.
Poor Fit: Unbounded Natural Language
Avoid when: users can describe recurrence patterns that have no RRULE equivalent, such as 'every payday', 'whenever the board meets', or 'during school terms'. Guardrail: require the prompt to output an unsupported_pattern flag and a human-readable explanation; route flagged outputs to a manual review queue instead of guessing.
Required Inputs: Anchor Context
Risk: recurrence rules depend on a start date, timezone, and sometimes an end condition. Without these, the model may hallucinate defaults. Guardrail: always provide [START_DATE], [TIMEZONE], and [END_CONDITION] as explicit input fields; never rely on the model to infer them from context alone.
Operational Risk: Silent Compliance Failures
Risk: a generated RRULE may be syntactically valid but semantically wrong—producing events on the wrong day or skipping occurrences. Guardrail: include a human_readable_confirmation field in the output schema and display it to the user for verification before saving; log all confirmations for audit.
Operational Risk: Timezone Drift
Risk: recurrence rules without explicit timezone anchoring can shift across DST boundaries, causing events to land at unexpected times. Guardrail: always embed the IANA timezone in the RRULE using the TZID parameter; test generated rules against DST transition dates in your eval suite.
Poor Fit: High-Volume Unsupervised Ingestion
Avoid when: processing thousands of recurrence descriptions per minute without human review. Guardrail: implement a confidence threshold; route low-confidence normalizations to a dead-letter queue for manual inspection. Never auto-commit unverified RRULE strings to production calendars at scale.
Copy-Ready Prompt Template
A reusable prompt template with square-bracket placeholders that converts natural language recurrence descriptions into structured RRULE strings and human-readable confirmations.
The prompt template below is designed to be dropped into your application's model call. It accepts a natural language recurrence description, optional context like a start date or timezone, and a set of constraints, and returns a structured JSON object containing the normalized RRULE, a human-readable confirmation, and flags for unsupported patterns. All placeholders use square brackets and are meant to be replaced by your application logic before the request is sent to the model.
textYou are a recurrence rule normalization engine. Your job is to convert natural language descriptions of repeating events into RFC 5545 compliant RRULE strings. ## INPUT Natural language recurrence description: [RECURRENCE_DESCRIPTION] Optional context: - Event start date (ISO 8601): [START_DATE] - Timezone: [TIMEZONE] - Known constraints: [CONSTRAINTS] ## OUTPUT SCHEMA Return ONLY valid JSON matching this schema: { "rrule": "string (RFC 5545 RRULE, or null if unsupported)", "human_readable": "string (plain English confirmation of the recurrence pattern)", "is_supported": "boolean (false if the pattern cannot be expressed as a standard RRULE)", "unsupported_reasons": ["string (list of reasons why the pattern is unsupported, empty if supported)"], "warnings": ["string (non-blocking concerns like DST ambiguity, empty if none)"], "confidence": "number between 0.0 and 1.0" } ## RULES 1. Generate RRULE strings compliant with RFC 5545. 2. Use the DTSTART from [START_DATE] if provided; otherwise omit DTSTART from the RRULE. 3. If the recurrence pattern cannot be expressed as a standard RRULE (e.g., 'every last weekday of the month that is not a holiday'), set is_supported to false and leave rrule as null. 4. Include a human_readable confirmation that a non-technical user could verify. 5. Flag any ambiguities in the warnings array (e.g., 'biweekly' could mean twice a week or every two weeks — state which interpretation was used). 6. If the description is vague or incomplete, set confidence below 0.8 and explain in warnings. 7. Do not invent dates, times, or recurrence details not present in the input. ## EXAMPLES Input: "Every Monday at 9am starting January 6, 2025" Output: { "rrule": "DTSTART:20250106T090000\nRRULE:FREQ=WEEKLY;BYDAY=MO", "human_readable": "Every Monday at 9:00 AM starting January 6, 2025", "is_supported": true, "unsupported_reasons": [], "warnings": [], "confidence": 0.98 } Input: "Every other Tuesday and Thursday until December" Output: { "rrule": "DTSTART:20250101T000000\nRRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,TH;UNTIL=20251231T235959", "human_readable": "Every other week on Tuesday and Thursday until December 31, 2025 (assuming start date of January 1, 2025 and end of December)", "is_supported": true, "unsupported_reasons": [], "warnings": ["Start date not provided, assumed January 1, 2025", "End date not specified, assumed December 31, 2025"], "confidence": 0.75 }
To adapt this template for your system, replace each square-bracket placeholder with values from your application context. The [RECURRENCE_DESCRIPTION] field should contain the raw user input or natural language text. [START_DATE] and [TIMEZONE] should be injected from your event or calendar record when available. The [CONSTRAINTS] field can carry business rules such as 'no weekend events' or 'only future dates'. If your application already has a known output schema, replace the JSON schema block with your own contract. For high-volume production use, add a post-processing step that validates the RRULE string against an RFC 5545 parser before storing it, and log any outputs where is_supported is false or confidence falls below your threshold for human review.
Prompt Variables
Placeholders required by the Recurring Event Rule Normalization prompt. Replace each with a concrete value or wire it to an upstream data source before sending the request.
| Placeholder | Purpose | Example | Validation Notes |
|---|---|---|---|
[RECURRENCE_DESCRIPTION] | Natural language description of the repeating event pattern to normalize. | Every other Tuesday at 10am, starting March 1st 2025, until end of year. | Required. Must be a non-empty string. Reject if input is only whitespace or a single word without temporal meaning. |
[START_DATE] | Anchor date for the recurrence rule. Used as DTSTART in the generated RRULE. | 2025-03-01 | Required. Must parse as ISO 8601 date (YYYY-MM-DD). Reject if missing or if date is nonsensical (e.g., year 0000). |
[TIMEZONE] | IANA timezone identifier for the event. Used to resolve ambiguous local times and DST transitions. | America/Chicago | Required. Must be a valid IANA timezone string. Validate against a known timezone list. Reject free-text like 'Central Time'. |
[OUTPUT_FORMAT] | Target output structure: 'rrule_string', 'structured_object', or 'both'. | both | Required. Must be one of the three allowed enum values. Reject any other value. Default to 'both' if null. |
[UNSUPPORTED_PATTERN_ACTION] | Behavior when the description contains a recurrence pattern that cannot be expressed in RRULE. | flag_and_continue | Required. Must be 'flag_and_continue', 'error', or 'best_effort'. Reject unknown values. Controls whether the prompt returns a partial result or aborts. |
[MAX_RRULE_LENGTH] | Maximum character length for the generated RRULE string before truncation is flagged. | 500 | Optional. Must be a positive integer if provided. If null or missing, default to 500. Reject negative values or zero. |
[LOCALE_HINTS] | Locale context for resolving week start day, holiday references, or regional date expressions in the description. | en-US | Optional. Must be a BCP 47 language tag if provided. If null, default to 'en-US'. Reject malformed tags. |
[ADDITIONAL_CONSTRAINTS] | Extra business rules or constraints to apply during normalization, such as excluding specific dates or capping occurrences. | Exclude 2025-07-04. Maximum 12 occurrences. | Optional. If provided, must be a non-empty string. If null, no extra constraints are applied. Validate that constraints do not contradict the recurrence description. |
Implementation Harness Notes
How to wire the Recurring Event Rule Normalization prompt into a production scheduling or calendar integration pipeline.
This prompt is designed to sit inside a post-extraction normalization layer, not as a direct user-facing chatbot. The typical caller is a calendar integration service, a scheduling API backend, or a data ingestion pipeline that has already extracted a natural language recurrence description from an email, a meeting transcript, a booking form, or a legacy system export. The caller should pass that extracted text as [RECURRENCE_DESCRIPTION] along with an optional [ANCHOR_TIMESTAMP] to resolve relative references like 'every other Monday starting next week.' The prompt returns a structured JSON payload containing a validated RRULE string, a human-readable confirmation, and an unsupported_patterns flag. Do not use this prompt for real-time chat interactions where the user is iteratively refining a recurrence rule; a multi-turn interface with a structured recurrence builder is more appropriate for that use case.
Wire the prompt into a stateless async worker or a request-response API endpoint. The application layer should enforce a strict JSON schema on the model's response before it reaches any downstream system. If the response fails schema validation—missing required fields, malformed RRULE syntax, or a normalized_rrule that does not parse as valid RFC 5545—the harness should retry once with the validation error injected into the [PREVIOUS_ERRORS] placeholder. After a second failure, log the full input, output, and validation trace, then route to a human review queue. For high-volume pipelines, consider batching multiple descriptions into a single request with a JSON array input and a corresponding array output schema to reduce API overhead, but keep batch sizes small (5-10 items) to avoid confusing the model across unrelated recurrence patterns.
Model choice matters here. Use a model with strong code and structured output capabilities, such as gpt-4o, claude-3-5-sonnet, or an equivalent. Avoid smaller or older models that may hallucinate RRULE property names or mishandle BYDAY ordinal values. Set temperature=0 to maximize deterministic RRULE generation. Enable structured outputs or JSON mode if the provider supports it, and always validate the RRULE string against an RFC 5545 parser library (such as rrule.js or dateutil.rrule in Python) before persisting the result. The unsupported_patterns field is a critical safety valve: if the model flags a pattern as unsupported, your application must not silently drop it. Instead, store the original description alongside the flag and surface it in an admin review interface so a human can author the correct RRULE or decide on an alternative representation.
For observability, instrument the harness with metrics on validation pass rate, retry rate, unsupported pattern frequency, and human review queue depth. Log every input description, the generated RRULE, the human-readable confirmation, and the validation result. This trace data is essential for debugging edge cases—such as 'every last weekday of the month' or 'biweekly on the 31st'—that may parse correctly but produce unexpected scheduling behavior. Set up a periodic eval run against a golden dataset of 50-100 recurrence descriptions with known-correct RRULE outputs, including tricky cases like monthly-by-day with skip logic, yearly patterns with timezone-aware exclusions, and descriptions that contain contradictory constraints. Run this eval on every prompt version change and on every model provider upgrade to catch regressions before they affect production calendars.
Common Failure Modes
Recurring event normalization is brittle because natural language is ambiguous and RRULE syntax is strict. These are the most common production failures and how to prevent them before they corrupt a calendar system.
Silent RRULE Syntax Violations
Risk: The model generates a string that looks like an RRULE but violates RFC 5545 (e.g., invalid property order, missing required parts, or illegal character combinations). Downstream parsers reject it silently or with cryptic errors. Guardrail: Always run the output through a strict RFC 5545 validator before storage. If validation fails, route to a repair prompt with the validator's error message as context, not a generic retry.
COUNT and UNTIL Collision
Risk: The model includes both COUNT and UNTIL in the same RRULE, which is explicitly forbidden by the spec. This often happens when the user says 'for the next 10 weeks' and the model also calculates an end date. Guardrail: Add a post-processing check that detects dual presence and removes the less specific constraint based on a deterministic rule (e.g., prefer UNTIL if both exist). Log the collision for prompt improvement.
Timezone Assumption Drift
Risk: The user says 'every Monday at 9 AM' without specifying a timezone. The model assumes UTC or its training-data default, producing events at the wrong local time after DST changes. Guardrail: Require a timezone input field. If missing, inject the system's default timezone explicitly into the prompt as [DEFAULT_TIMEZONE] and include a tzid parameter in the output. Never let the model guess.
Unsupported Pattern Hallucination
Risk: The user describes a recurrence like 'every other weekend' or 'the last weekday of the month' that requires complex BYDAY and BYSETPOS combinations. The model confidently generates an incorrect or incomplete rule instead of flagging it. Guardrail: Include a required is_fully_supported boolean in the output schema. Pair the prompt with a test suite of known-unsupported phrases. If false, route to a human review queue or a simpler confirmation prompt.
Interval Misinterpretation from Natural Language
Risk: Phrases like 'every other week' or 'bi-weekly' are ambiguous (every two weeks vs. twice a week). The model picks one arbitrarily, leading to incorrect schedules. Guardrail: Add a disambiguation_note field to the output schema. If the input contains known-ambiguous terms, force the model to state its interpretation explicitly. Surface this note in the UI for user confirmation before saving.
Start Date and Rule Mismatch
Risk: The DTSTART value doesn't align with the recurrence pattern (e.g., DTSTART is a Tuesday but the rule says 'every Monday'). The RRULE is technically valid but logically broken. Guardrail: Implement a semantic validator that checks if DTSTART matches the first instance defined by the BYDAY rule. If mismatched, flag for correction and suggest adjusting DTSTART to the next valid occurrence.
Evaluation Rubric
Criteria for evaluating the quality of normalized RRULE outputs before integrating into production scheduling systems.
| Criterion | Pass Standard | Failure Signal | Test Method |
|---|---|---|---|
RFC 5545 Compliance | Output RRULE string parses without error by an RFC 5545 validator | Validator throws parse error or rejects the string | Run output through a standard iCalendar parsing library (e.g., python-dateutil rrulestr) and confirm no exceptions |
Semantic Equivalence | Generated RRULE describes the same recurrence pattern as the natural language input | RRULE generates occurrences that conflict with the input description (e.g., wrong day, wrong interval) | Generate the next 5 occurrence dates from the RRULE and compare against manually interpreted expected dates from the input |
Human-Readable Confirmation Accuracy | The confirmation text correctly restates the recurrence rule in plain language without contradiction | Confirmation text describes a different schedule than the RRULE or input text | Pairwise comparison by a second LLM judge or human reviewer checking for factual consistency between input, RRULE, and confirmation |
Unsupported Pattern Flagging | Inputs containing non-RRULE-compatible patterns (e.g., 'every weekday except holidays') are flagged with unsupported_reason populated | Flag is false for an unsupported pattern, or true with an empty or irrelevant reason | Test with a curated set of 10 known-unsupported recurrence descriptions and verify flag=true and reason is non-empty and relevant |
COUNT and UNTIL Mutual Exclusivity | Output RRULE never contains both COUNT and UNTIL in the same rule | Both COUNT and UNTIL are present in the RRULE string | String search for 'COUNT=' and 'UNTIL=' in the output; assert not both found |
Timezone Handling | DTSTART and any timezone-sensitive parts reflect the input timezone context or UTC when unspecified | RRULE produces occurrences shifted by hours due to ignored or defaulted timezone | Inject inputs with explicit timezone context (e.g., 'every Monday at 9am EST') and verify DTSTART includes the correct TZID or UTC offset |
Input Ambiguity Handling | Ambiguous inputs (e.g., 'biweekly' without clarification) produce a confidence score below threshold or a clarification request | Model confidently produces a single RRULE for a genuinely ambiguous input | Test with 'biweekly meeting' and check if confidence < 0.9 or output includes a clarification note rather than a single RRULE |
Edge Case: Month-End Rules | Rules like 'last day of month' produce BYMONTHDAY=-1 or equivalent correct representation | Output uses BYMONTHDAY=31 or other incorrect fixed day | Test with 'monthly on the last day' and verify BYMONTHDAY=-1 in the RRULE |
Enabling Efficiency, Speed & Accuracy
Intelligent Analysis, Decision & Execution
We build AI systems for teams that need search across company data, workflow automation across tools, or AI features inside products and internal software.
Talk to Us
Search across company data
Give teams answers from docs, tickets, runbooks, and product data with sources and permissions.
Useful when people spend too long searching or get different answers from different systems.

Automate internal workflows
Use AI to route work, draft outputs, trigger actions, and keep approvals and logs in place.
Useful when repetitive work moves across multiple tools and teams.

Add AI to products and internal tools
Build assistants, guided actions, or decision support into the software your team or customers already use.
Useful when AI needs to be part of the product, not a separate tool.
Adapt This Prompt
How to adapt
Use the base prompt with a single model call and minimal post-processing. Accept the RRULE string and human-readable confirmation as-is. Skip strict RFC 5545 validation in the prompt layer—validate in application code instead.
Watch for
- Model inventing RRULE properties not present in the input (e.g., adding COUNT when only UNTIL was implied)
- Overly broad interpretation of vague phrases like 'every other week' without asking for clarification
- Missing the unsupported-pattern flag when the recurrence is too complex for RRULE

About the author
Prasad Kumkar
CEO & MD, Inference Systems
Prasad Kumkar is the CEO & MD of Inference Systems and writes about AI systems architecture, LLM infrastructure, model serving, evaluation, and production deployment. Over 5+ years, he has worked across computer vision models, L5 autonomous vehicle systems, and LLM research, with a focus on taking complex AI ideas into real-world engineering systems.
His work and writing cover AI systems, large language models, AI agents, multimodal systems, autonomous systems, inference optimization, RAG, evaluation, and production AI engineering.
Partnered with leading AI, data, and software stack.
How We Work
Custom AI workflows for your Business
One-fit-all AI don't work for modern businesses. At Inferensys, we aim to understand your business & custom requirements; which we use to define most efficient agentic workflows, the data, and the tools for your business.
01
Review the use case
We understand the task, the users, and where AI can actually help.
Read more02
Pick the right approach
We define what needs search, automation, or product integration.
Read more03
Build the first useful version
We implement the part that proves the value first.
Read more04
Improve from there
We add the checks and visibility needed to keep it useful.
Read moreThe first call is a practical review of your use case and the right next step.
Talk to Us