Source Code

<div class="demo">
  <label class="field-label" for="nlDate">Due date</label>
  <div class="nl-date-field">
    <input type="text" id="nlDate" class="nl-input" placeholder="e.g. tomorrow, next friday, in 3 days, aug 30" autocomplete="off" />
    <div class="nl-result" id="nlResult">
      <span class="nl-result-dot" id="nlDot"></span>
      <span class="nl-result-text" id="nlResultText">Start typing a date in plain English</span>
    </div>
  </div>

  <div class="nl-chips">
    <button type="button" class="nl-chip" data-value="today">today</button>
    <button type="button" class="nl-chip" data-value="tomorrow">tomorrow</button>
    <button type="button" class="nl-chip" data-value="next monday">next monday</button>
    <button type="button" class="nl-chip" data-value="in 2 weeks">in 2 weeks</button>
    <button type="button" class="nl-chip" data-value="end of month">end of month</button>
  </div>

  <input type="hidden" id="nlHiddenIso" name="dueDate" />
</div>

Natural Language Date Input — Parse "next friday" / "in 3 days" into a Real Date

Natural Language Date Input — Type "next friday", Get a Real Date · Forms · Plain HTML, CSS & JS · Live preview

What's included

Features

Parses literal keywords: today, tomorrow, yesterday, end of month
Parses relative phrases: "in N days/weeks/months", "N days from now/ago"
Parses weekday phrases with correct next-vs-this-week disambiguation for "next friday" vs "friday"
Parses month-day phrases like "aug 30" and automatically rolls to next year if the date already passed
Falls back to the native Date constructor for ISO and slash-formatted dates the browser already understands
Live result indicator with color-coded success/error states as the user types
Hidden ISO-formatted field kept in sync for clean form submission, decoupled from the free-text phrase
One-click suggestion chips demonstrating supported phrase shapes

About this UI Snippet

Natural Language Date Parsing — Turning Free Text into a Real Date

Screenshot of the Natural Language Date Input — Type "next friday", Get a Real Date snippet rendered live

Traditional date pickers force users to click through a calendar grid even when they know exactly what they mean — "next friday" is faster to type than it is to find on a calendar widget, especially on mobile. This snippet implements a genuine natural-language date parser: type a phrase, and parseNaturalDate() resolves it to an actual Date object shown in both a human-readable format and a hidden ISO field ready for form submission.

Why pattern order matters

The parser checks patterns from most specific to least specific — literal keywords like "today" first, then structured patterns like "in 3 days", then weekday phrases, then month-day phrases, and only falls back to the browser's native Date constructor last. This ordering isn't arbitrary: a looser pattern checked first could accidentally consume input meant for a more specific rule (for example, if the weekday check ran before the "in N days" check and happened to match a stray word, the number would be lost). Each regex is anchored with ^ and $ so it only matches when the *entire* input fits that shape, preventing partial matches from producing a wrong date silently.

The trickiest case: "next friday" vs. plain "friday"

Real natural-language date libraries all have to make a judgment call here, and this one follows the most common convention: saying "friday" alone (with no "next") on any day still means *the upcoming Friday* — including today's date if today happens to be Friday, the code instead rolls forward a full week rather than resolving to "right now," since a bare weekday name almost always means the next occurrence. Adding the word "next" explicitly pushes the result one additional week further out — so on a Wednesday, "friday" means two days away, while "next friday" means nine days away. This distinction is encoded in the isNext check inside the weekday branch, adding exactly one extra week when the word "next" was present.

Rolling month-day phrases into the correct year

For a phrase like "aug 30" typed in September, the naive result would be a date nine months in the *past*. The parser checks whether the constructed date already fell before today and, if so, rolls the year forward by one — so writing a month-and-day phrase always resolves to the next upcoming occurrence of that date, never a stale one from earlier in the current year.

Falling back to the native parser as a safety net

Rather than rejecting anything that doesn't match a known phrase shape, the last branch hands the raw string to new Date(raw) — this lets ISO strings (2026-09-01), US-style slash dates (08/30/2026), and other formats the browser already understands pass through correctly, so the custom patterns only need to cover the *conversational* phrasing a calendar picker can't.

Keeping a real ISO value in sync for form submission

The visible input holds the free-text phrase the user typed, but a hidden <input type="hidden"> field is kept in sync with the parsed date's ISO form (YYYY-MM-DD) on every keystroke — this is the value that actually gets submitted with the form, so the backend never has to parse natural language itself; it only ever sees a clean, unambiguous date string.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Ask an AI assistant to walk through why the parser checks phrase patterns in a specific order — most specific first, generic fallback last — and what would break if that order were reversed. It's also worth asking for additional phrase support (e.g. "next quarter", "in N business days" that skips weekends), or for a version that also accepts relative time components like "next friday at 3pm" and stores a full datetime instead of a date-only value.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a natural-language date input in plain HTML, CSS, and vanilla JavaScript — no external date library.

Requirements:
- A single text input where the user can type phrases like "today", "tomorrow", "next friday", "in 3 days", "2 weeks from now", "end of month", or a month-and-day phrase like "aug 30".
- A parsing function that resolves each recognized phrase shape to a real Date object, checking more specific patterns before generic ones so input is never mismatched.
- Correctly distinguish "friday" (resolves to the nearest upcoming Friday, rolling forward a week even if today is Friday) from "next friday" (one additional week beyond that).
- For month-day phrases, if the resulting date has already passed this year, roll the year forward by one so the phrase always resolves to an upcoming date.
- Fall back to the browser's native Date constructor for any input that doesn't match a custom phrase pattern, so ISO and slash-formatted dates still work.
- Show a live result area below the input that updates on every keystroke: a success state with the resolved, human-readable date when parsing succeeds, and a clearly different error state when it fails.
- Keep a second, hidden form field in sync with the successfully parsed date in YYYY-MM-DD format, separate from the visible free-text input, so a real form submission sends a clean date value.
- Include a handful of clickable suggestion chips that fill the input with example phrases.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Type a phrase into the fieldTry "tomorrow", "next friday", "in 3 days", or "aug 30" — the result box below updates live as you type.
  2. 2
    Watch the result indicatorA green dot and resolved date mean the phrase parsed successfully; a red dot means the parser did not recognize the input.
  3. 3
    Click a suggestion chipThe chips below the input fill in common phrases instantly, useful as both a shortcut and a hint for what the parser understands.
  4. 4
    Read the hidden ISO valueThe #nlHiddenIso input holds a YYYY-MM-DD value in sync with the parsed date — submit this field to your backend instead of the free-text phrase.
  5. 5
    Extend parseNaturalDate() for more phrasesAdd new regex branches following the existing pattern-order convention (specific phrases before generic fallbacks) to support phrases like "next quarter" or your own domain-specific shorthand.

Real-world uses

Common Use Cases

Task due-date fields
Let users type "next monday" instead of clicking through a calendar grid to set a task or reminder date.
Quick date filters
Pair with a search or report filter UI so users can type "last 2 weeks" style shortcuts instead of picking two calendar dates.
CHAT
Command-bar date arguments
Use inside a command palette or slash-command input where users type structured commands including a date argument.
Mobile-first quick entry
Typing a short phrase is faster than navigating a touch calendar widget on small screens.
Related: Restaurant Table Reservation Form
See the Restaurant Table Reservation Form for a related forms pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

No — a bare weekday name always resolves to the next upcoming occurrence, rolling forward a full week even if today matches. This matches how most people mean it conversationally ("let's meet friday" said on a Friday almost always means next week).

"friday" resolves to the nearest upcoming Friday. "next friday" adds one additional week on top of that, matching the common (if occasionally ambiguous) convention that "next" pushes past the nearest occurrence.

The result box turns red, shows a "couldn't parse that" message, and the hidden ISO field is cleared to an empty string — your form validation should check that hidden field is non-empty before allowing submission.

Yes — anything not matched by the custom phrase patterns is handed to JavaScript's native Date constructor as a fallback, which understands ISO dates and several other common formats.

Yes — add a new regex branch inside parseNaturalDate() following the existing pattern, placed before the native-Date fallback and after any more-specific patterns it might otherwise conflict with.

The visible field holds whatever free-text phrase the user typed, which is not a reliable value to submit to a server. The hidden field always holds the parsed, unambiguous YYYY-MM-DD value, so the backend receives clean structured data regardless of how the user phrased their input.