Validate user-entered dates in Classic ASP

A Classic ASP form can collect year, month and day separately, then validate them on the server before creating a Date value. This prevents ambiguous date strings and rejects impossible dates such as February 31.

<%
Dim yearNo, monthNo, dayNo, candidate, validDate
yearNo = 2024: monthNo = 2: dayNo = 29
validDate = False
If monthNo >= 1 And monthNo <= 12 And dayNo >= 1 And dayNo <= 31 Then
  candidate = DateSerial(yearNo, monthNo, dayNo)
  validDate = (Year(candidate) = yearNo And Month(candidate) = monthNo And Day(candidate) = dayNo)
End If
Response.Write validDate
%>

Output: True. February 29 exists in 2024. In an actual form, validate that the input contains integers before performing these comparisons.

On this page — Show page sectionsHide page sections

What to validate

CheckReason
Submitted using POSTOnly process when the form is submitted
Whole-number textReject decimals, signs and non-numeric characters
Year, month and day rangesRequire year 1000–9999, month 1–12 and day 1–31
DateSerial round-tripReject impossible combinations such as February 30
Output encodingEncode any user-provided text before including it in HTML

Complete Classic ASP date-input form

Save this complete example as an .asp page on IIS. It validates user input on the server, then displays the resulting date in a numeric year-month-day format. It uses RegExp to reject non-integer input before converting it.

<%@ Language=VBScript %>
<% Option Explicit %>
<%
Dim submitted, monthText, dayText, yearText
Dim monthNo, dayNo, yearNo, myDate, validDate
Dim digits, yearDigits, m, d
submitted = (Request.Form("todo") = "submit")
validDate = False
If submitted Then
  monthText = Trim(Request.Form("month"))
  dayText = Trim(Request.Form("day"))
  yearText = Trim(Request.Form("year"))

  Set digits = New RegExp
  digits.Pattern = "^[0-9]{1,2}$"
  Set yearDigits = New RegExp
  yearDigits.Pattern = "^[0-9]{4}$"

  If digits.Test(monthText) And digits.Test(dayText) And yearDigits.Test(yearText) Then
    monthNo = CInt(monthText)
    dayNo = CInt(dayText)
    yearNo = CInt(yearText)
    If yearNo >= 1000 And yearNo <= 9999 And _
       monthNo >= 1 And monthNo <= 12 And _
       dayNo >= 1 And dayNo <= 31 Then
      myDate = DateSerial(yearNo, monthNo, dayNo)
      validDate = (Year(myDate) = yearNo And _
                   Month(myDate) = monthNo And Day(myDate) = dayNo)
    End If
  End If

  If validDate Then
    Response.Write "<p>Valid date: " & Year(myDate) & "-" & _
      Right("0" & Month(myDate), 2) & "-" & _
      Right("0" & Day(myDate), 2) & "</p>"
  Else
    Response.Write "<p>Please enter a valid date.</p>"
  End If
End If
%>
<!doctype html>
<html><head><title>Validate a date</title></head><body>
<form method="post" action="">
  <input type="hidden" name="todo" value="submit">
  <label>Month <select name="month" required>
  <% For m = 1 To 12 %>
    <option value="<%=m%>"><%=MonthName(m)%></option>
  <% Next %>
  </select></label>
  <label>Day <select name="day" required>
  <% For d = 1 To 31 %>
    <option value="<%=d%>"><%=d%></option>
  <% Next %>
  </select></label>
  <label>Year <input type="number" name="year" min="1000" max="9999" value="2024" required></label>
  <button type="submit">Validate date</button>
</form>
</body></html>

The form purposely uses a full four-digit year, and the server validates every field even though the browser controls also specify ranges. Month and day selections do not imply that the combination is valid.

What happens with invalid dates?

Submitted valuesResult
2024 / 2 / 29Valid — leap day
2023 / 2 / 29Invalid — not a leap year
2026 / 4 / 31Invalid — April has 30 days
2026 / 13 / 1Invalid — month out of range
2026 / 2.5 / 10Invalid — not a whole-number month
2026 / 2 / blankInvalid — missing day

Why DateSerial() needs a round-trip check

<%
Dim monthNo, dayNo, yearNo, myDate
monthNo = 2: dayNo = 31: yearNo = 2024
myDate = DateSerial(yearNo, monthNo, dayNo)
Response.Write Month(myDate) & "/" & Day(myDate) & "/" & Year(myDate)
%>
3/2/2024

The function returned March 2 rather than rejecting February 31. Compare the resulting year, month, and day to the submitted numbers to detect the overflow.

Why IsDate() alone is not enough

IsDate() is designed to check whether a value can be recognized as a date under the current regional settings. It is not an exact validator for three separately submitted numeric components.

Security and user experience

Do not rely on HTML min, max or required attributes alone. Attackers can bypass browser checks. Reject malformed input server-side, avoid displaying raw submitted values, and never concatenate unvalidated form values into a SQL query.

Common problems

An overflow error typically means a value was converted to a numeric type with a smaller range than expected. A type mismatch often indicates that a value was converted before its format was validated. Use fixed numeric input rules before calling CInt or DateSerial().

Frequently asked questions

Why use four-digit years?

They avoid ambiguity around how two-digit year values are interpreted.

Does DateSerial() reject day 31 in April?

No. It rolls over into May; the validation must compare its components.

Should validation run in JavaScript or ASP?

You can add client-side assistance, but always perform authoritative validation on the ASP server.

What about a single date text field?

Specify a format and parse its numeric components explicitly rather than relying on locale-dependent text parsing.

Back to top ↑


ASP Home






✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer