How To Prefill Your Form Field With Today’s Date: Client vs. Server Time

A form entry without a trustworthy date is a lead you can’t route, a request you can’t prove you answered on time, and a report that won’t reconcile with your CRM. Plenty of form tools stamp the entry for you, but that stamp often lives only in the form plugin’s database. Once the submission moves into a spreadsheet, a webhook, or a marketing automation platform, the date has to travel as a field value, and that’s where teams get burned.
The burn usually comes from one assumption: that there is only one now. There are at least two. The visitor’s browser has its own clock and time zone, and your server has another. A visitor in Los Angeles submitting at 9:30 PM is already on tomorrow in UTC. Prefill the field with the wrong clock and your daily lead counts drift, your service-level timers start a day early, and a date picker quietly shows yesterday.
Decide which clock each field should represent, then set it with code that respects that choice. For a deeper look at how systems display, calculate, and synchronize time, read What Time Is It? How Our Systems Display, Calculate, Format, and Synchronize Dates and Times.
Table of Contents
Client Time Versus Server Time
Client time is whatever the visitor’s device says it is, in the visitor’s time zone. JavaScript reads it with new Date(). It is the right choice when the field means the date the visitor experienced, such as a requested appointment day or a date picker’s starting value. It is also the wrong choice for anything you need to audit, because a visitor can set their device clock to any value.
Server time comes from your web server and is set by your application, not the visitor. In PHP and WordPress, it is the clock you should trust for the moment a submission was received. The catch is that a server-rendered value is frozen into the HTML. If a page cache stores the form, every visitor sees the date the cache was built, not today.
- Use client time to prefill visible date pickers and to record what the visitor saw on their screen.
- Use server time for the official received timestamp, deadlines, and anything legal or contractual.
- Store UTC and convert for display. A UTC timestamp sorts and compares correctly no matter where the visitor or server sits.
- Record the visitor’s time zone alongside the UTC value so you can reconstruct their local time later.

toISOString() reports October 29 in UTC.Set Today’s Date With JavaScript
The most common bug in date prefill code is formatting the date with toISOString() and slicing off the first ten characters. That returns the UTC date, which is a different calendar day for part of every day almost everywhere in the world. Build the local date from the local getters instead.
<form id="lead-form">
<label for="visit-date">Date</label>
<input type="date" id="visit-date" name="visit_date">
<input type="hidden" id="submitted-local" name="submitted_local">
</form>
<script>
// Local calendar date as YYYY-MM-DD (the format input type="date" requires)
function localISODate(d = new Date()) {
const pad = (n) => String(n).padStart(2, '0');
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
}
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('visit-date').value = localISODate();
// Human-readable local date for notifications and spreadsheets
document.getElementById('submitted-local').value = new Intl.DateTimeFormat('en-US', {
year: 'numeric', month: '2-digit', day: '2-digit'
}).format(new Date());
});
</script> localISODate()usesgetFullYear(),getMonth(), andgetDate(), which all read the visitor’s local time zone.getMonth()is zero-based, so it adds one.padStart(2, '0')adds the leading zeros thatinput type="date"requires. A value such as2026-1-5is rejected and the field stays empty.Intl.DateTimeFormatformats the date for people. Use it for text and hidden fields that humans read, never as the value of a date input, because its output changes with the locale.DOMContentLoadedwaits until the form exists in the DOM before setting values, so the script works in the page head or footer.
Prefill Date and Datetime-Local Inputs Without UTC Errors
A datetime-local input expects local time in YYYY-MM-DDTHH:MM format with no time zone designator. Passing it toISOString() fails twice: the value ends in Z, which the input rejects, and the hour is UTC rather than local.
<input type="datetime-local" id="appointment" name="appointment">
<script>
function localISODateTime(d = new Date()) {
const pad = (n) => String(n).padStart(2, '0');
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}
document.getElementById('appointment').value = localISODateTime();
</script> Two other shortcuts cause the same off-by-one-day problem. Setting input.valueAsDate = new Date() on a date input uses the UTC date, and new Date('2026-10-29') parses a date-only string as midnight UTC, which displays as the previous evening for anyone west of Greenwich. Parse date-only strings by splitting them into numbers and passing those to new Date(year, month - 1, day).
// Wrong for most of the Americas: midnight UTC is the previous local evening
new Date('2026-10-29').toLocaleDateString(); // "10/28/2026" in Indianapolis
// Right: build the date from its parts in local time
const [y, m, d] = '2026-10-29'.split('-').map(Number);
new Date(y, m - 1, d).toLocaleDateString(); // "10/29/2026" Capture the Visitor’s Time Zone in Hidden Fields
When the record has to show both what the visitor saw and the exact instant they submitted, send three hidden values and let your server or CRM convert as needed. This also pairs well with the attribution data covered in how to populate hidden form fields via UTM parameters.
<input type="hidden" name="submitted_utc" id="submitted-utc">
<input type="hidden" name="client_time_zone" id="client-time-zone">
<input type="hidden" name="client_utc_offset" id="client-utc-offset">
<script>
document.getElementById('lead-form').addEventListener('submit', () => {
const now = new Date(); // stamp at submit, not at page load
document.getElementById('submitted-utc').value = now.toISOString(); // 2026-10-29T12:40:51.529Z
document.getElementById('client-time-zone').value = Intl.DateTimeFormat().resolvedOptions().timeZone; // America/Indiana/Indianapolis
document.getElementById('client-utc-offset').value = -now.getTimezoneOffset(); // minutes east of UTC, e.g. -240
});
</script> toISOString() is exactly right here because this field is meant to be UTC. getTimezoneOffset() returns minutes behind UTC, so the sign is flipped to produce the familiar convention where Indianapolis in summer is -240. Stamping inside the submit handler records when the visitor pressed the button, not when the page loaded twenty minutes earlier.
The jQuery Version
If your site already loads jQuery, the same logic fits in a ready handler. Do not add jQuery just for this. The plain JavaScript above runs in every current browser.
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
$(function () {
const d = new Date();
const pad = (n) => String(n).padStart(2, '0');
$('#visit-date').val(`${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`);
$('#lead-form').on('submit', function () {
$('#submitted-utc').val(new Date().toISOString());
});
});
</script> Set the Date on the Server With PHP and WordPress
PHP’s date() uses the PHP default time zone, which is often UTC on a server and has nothing to do with your WordPress setting. Name the zone explicitly with DateTimeImmutable.
<?php
$local = new DateTimeImmutable( 'now', new DateTimeZone( 'America/Indiana/Indianapolis' ) );
echo $local->format( 'Y-m-d' ); // 2026-10-29 (business date)
$utc = new DateTimeImmutable( 'now', new DateTimeZone( 'UTC' ) );
echo $utc->format( DATE_ATOM ); // 2026-10-29T12:40:59+00:00 (store this) WordPress keeps its own time zone under Settings, General. Its helpers read that setting so you do not have to hard-code a zone. If you need today’s date inside post content rather than a form, see this shortcode that displays today with optional formatting and calculations.
wp_date( 'Y-m-d' )formats the current moment (or a Unix timestamp you pass) in the site time zone. This is the recommended formatter.current_time( 'mysql' )returns site-localY-m-d H:i:s. Passtrueas the second argument for the UTC (GMT) version.current_datetime()returns aDateTimeImmutablealready set to the site time zone.wp_timezone()returns the site’sDateTimeZonefor your own conversions.
<?php
// Prefill a date input with the site's local date (server time)
?>
<input type="date" name="received_date" value="<?php echo esc_attr( wp_date( 'Y-m-d' ) ); ?>">
<?php
// Stamp the official received time on save, in UTC, ignoring anything the browser sent
add_action( 'init', function () {
if ( isset( $_POST['lead_form_nonce'] ) && wp_verify_nonce( $_POST['lead_form_nonce'], 'lead_form' ) ) {
$received_utc = current_time( 'mysql', true ); // 2026-10-29 12:40:59
// save $received_utc with the entry
}
} ); 
date() follows the server default of UTC.Remember the cache warning. A value printed into the page by PHP is only as fresh as the cached copy. On cached pages, prefill visible fields with JavaScript and record the authoritative received time on the server when the form is submitted.
Default the Date in Popular Form Tools
Most form builders already have a native setting or merge tag for today’s date, so check for one before writing code. The WordPress plugins below evaluate their tags on the server, using the time zone in WordPress settings.
Gravity Forms
In Gravity Forms, open the Date field, go to Advanced, and set Default Value. With the Date Picker input type, {date_mdy} or {date_dmy} fills today’s date. Since version 2.6.0.1, the {today} merge tag accepts a format, such as {today:format:m/d/Y} or {today:format:Y-m-d}. For a Date field set to dropdowns, put {today:format:m}, {today:format:d}, and {today:format:Y} in the month, day, and year inputs. Gravity Forms output follows the time zone in WordPress settings. If you also pass a CRM record ID through the form, see how to pass and store a Salesforce contact ID with Gravity Forms.
{today:format:Y-m-d} WPForms
In WPForms, add a Hidden Field, open Advanced, and click Show Smart Tags next to Default Value. The Date Smart Tag inserts {date format="m/d/Y"}, and you can change the format with PHP date characters, such as {date format="Y-m-d H:i:s"}. WPForms notes that {entry_date} cannot be a default value because it only exists after submission.
{date format="Y-m-d"} Contact Form 7
Since version 5.3, Contact Form 7 accepts relative date expressions as the default value of a date form-tag, as well as in min and max. The value is converted to Y-m-d.
[date your-date "today"]
[date* delivery-date min:today "today+2days"] Ninja Forms
The Ninja Forms Date/Time field has no Default Value box. Enable its Default to Current Date setting instead, and the field displays the current date until the visitor picks another. For a hidden stamp, put the {other:date} merge tag in a Hidden field’s Default Value. Ninja Forms 3.14.10 fixed a bug where {other:date} reported UTC instead of local time, so update before you rely on it.
Formidable Forms
In Formidable Forms, open the Date field’s Advanced section and enter the [date] shortcode as the Default Value. It uses the format from Formidable’s Global Settings unless you pass one, and the offset option accepts any PHP strtotime() string. Smart default values are a premium feature.
[date format="Y-m-d"]
[date offset="+3 days" format="Y-m-d"] HubSpot Forms
For forms built in the current HubSpot forms editor, set the value from the page with HubSpot’s global form events. Register the listener before the embed code runs. The setFieldValue method accepts a date as a Unix timestamp in milliseconds, and passing midnight UTC of the visitor’s local date keeps the date from shifting. Replace 0-1/visit_date with your field’s internal name.
<script>
window.addEventListener('hs-form-event:on-ready', (event) => {
const form = HubSpotFormsV4.getFormFromEvent(event);
const d = new Date();
form.setFieldValue('0-1/visit_date', Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
});
</script>
<!-- HubSpot form embed code goes after this listener --> Legacy HubSpot forms use the onFormReady callback in hbspt.forms.create() instead.
Jotform
In Jotform, select the Date Picker, open its settings with the gear icon, go to Options, and set Default Date to Current. To default the time too, turn on the Time Field and set Default Time to Current. The value comes from the visitor’s device.
Typeform
Typeform has no setting to default a Date question to today. Every response already carries a submitted_at timestamp in UTC in the Responses API and webhook payloads, which is usually what you need. To bring a date in from your own page, pass it as a URL parameter (formerly called a hidden field) when you link to or embed the form.
<script>
const d = new Date();
const pad = (n) => String(n).padStart(2, '0');
const today = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
document.getElementById('typeform-link').href = `https://form.typeform.com/to/YOUR_FORM_ID#visit_date=${today}`;
</script> Google Forms
Google Forms records a Timestamp for every response automatically. To prefill a Date question, use Get pre-filled link from the form’s menu, enter any date, and copy the generated URL. The date parameter uses YYYY-MM-DD regardless of how the form displays it, so you can swap in today’s date with JavaScript.
<script>
const d = new Date();
const pad = (n) => String(n).padStart(2, '0');
const today = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
// entry.123456789 comes from your pre-filled link
document.getElementById('google-form-link').href =
`https://docs.google.com/forms/d/e/YOUR_FORM_ID/viewform?usp=pp_url&entry.123456789=${today}`;
</script> Marketo
In Marketo, use the Forms 2.0 JavaScript API. MktoForms2.whenReady() hands you the form, form.vals() sets fields that already exist on it, and form.addHiddenFields() adds or updates hidden ones. Use the field’s API name, not its label.
<script>
MktoForms2.whenReady(function (form) {
const d = new Date();
const pad = (n) => String(n).padStart(2, '0');
form.addHiddenFields({
formSubmittedLocalDate: `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`,
formSubmittedUTC: d.toISOString()
});
});
</script> Webflow
The Webflow form builder has no native date field. Add an Embed element inside the Form Block with a standard input type="date", then set its value with the localISODate() function from earlier in the page’s custom code. The input’s name becomes the field name in your submissions.
<!-- Embed element inside the Webflow Form Block -->
<input type="date" id="visit-date" name="visit-date">
<!-- Page settings, custom code before </body> -->
<script>
const d = new Date();
const pad = (n) => String(n).padStart(2, '0');
document.getElementById('visit-date').value = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
</script> Which Clock Should Your Form Trust?
Let the browser fill what the visitor sees, let the server record when the entry arrived, and send UTC plus the visitor’s time zone to every system downstream. If you’re building more date and time controls, this dynamic time select dropdown with intervals uses the same local-time approach. Get those three decisions right and your lead reports, routing rules, and follow-up timers will agree with each other no matter where your visitors live.







