<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="VB6Parse Library Reference - dateserial - Datetime">
<title>dateserial - Datetime - VB6Parse Library Reference</title>
<link rel="stylesheet" href="../../../assets/css/style.css">
<link rel="stylesheet" href="../../../assets/css/docs-style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
<script src="../../../assets/js/theme-switcher.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/vbnet.min.js"></script>
<script>hljs.highlightAll();</script>
</head>
<body>
<header class="docs-header">
<div class="container">
<h1><a href="../../../index.html">VB6Parse</a> / <a href="../../../library/index.html">Library</a> / <a href="../../../library/functions/datetime/index.html">Datetime</a> / dateserial</h1>
<p class="tagline">VB6 Library Reference</p>
</div>
</header>
<nav class="docs-nav">
<div class="container">
<a href="../../../index.html">Home</a>
<a href="../../../library/index.html">Library Reference</a>
<a href="../../../documentation.html">Documentation</a>
<a href="https://docs.rs/vb6parse" target="_blank">API Docs</a>
<a href="https://github.com/scriptandcompile/vb6parse" target="_blank">GitHub</a>
<button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme">
<span class="theme-icon">🌙</span>
</button>
</div>
</nav>
<main class="container">
<article class="library-item">
<h1 id="dateserial-function">DateSerial Function</h1>
<p>Returns a <code>Variant</code> (<code>Date</code>) for a specified year, month, and day.</p>
<h2 id="syntax">Syntax</h2>
<pre><code class="language-vbnet">DateSerial(year, month, day)</code></pre>
<h2 id="parameters">Parameters</h2>
<ul>
<li><strong>year</strong>: Required. <code>Integer</code> expression between 100 and 9999, inclusive, or a numeric
expression. Values from 0 to 29 are interpreted as 2000-2029; values from 30 to 99
are interpreted as 1930-1999.</li>
<li><strong>month</strong>: Required. <code>Integer</code> expression from 1 to 12, but can be any numeric expression
representing months from -32,768 to 32,767. Month values outside 1-12 adjust the year
accordingly.</li>
<li><strong>day</strong>: Required. <code>Integer</code> expression from 1 to 31, but can be any numeric expression
representing days from -32,768 to 32,767. Day values outside the valid range adjust
the month and year accordingly.</li>
</ul>
<h2 id="return-value">Return Value</h2>
<p>Returns a <code>Variant</code> of subtype <code>Date</code> representing the specified date. The time portion
is set to midnight (00:00:00).</p>
<h2 id="remarks">Remarks</h2>
<p>The <code>DateSerial</code> function is used to construct a date value from individual year, month,
and day components. It's particularly useful for date calculations and building dates
programmatically.
<strong>Important Characteristics:</strong>
- Accepts values outside normal ranges and adjusts automatically
- Month values > 12 or < 1 adjust the year
- Day values outside valid range adjust the month
- Can use 0 or negative values for relative date calculations
- Two-digit years: 0-29 → 2000-2029, 30-99 → 1930-1999
- Always returns midnight (00:00:00) for time portion
- Invalid combinations return compile-time or runtime errors</p>
<h2 id="range-adjustment-examples">Range Adjustment Examples</h2>
<pre><code class="language-vbnet">' Month adjustment
DateSerial(2025, 13, 1) ' Returns 1/1/2026 (13th month = Jan next year)
DateSerial(2025, 0, 1) ' Returns 12/1/2024 (0th month = Dec previous year)
DateSerial(2025, -1, 1) ' Returns 11/1/2024 (month -1 = Nov previous year)
' Day adjustment
DateSerial(2025, 1, 32) ' Returns 2/1/2025 (32nd day = Feb 1)
DateSerial(2025, 1, 0) ' Returns 12/31/2024 (0th day = last day of prev month)
DateSerial(2025, 1, -1) ' Returns 12/30/2024 (day -1)
' Combined adjustment
DateSerial(2025, 13, 32) ' Returns 2/1/2026</code></pre>
<h2 id="examples">Examples</h2>
<h3 id="basic-usage">Basic Usage</h3>
<pre><code class="language-vbnet">' Create a specific date
Dim birthday As Date
birthday = DateSerial(1990, 5, 15) ' May 15, 1990
' Create date from variables
Dim y As Integer, m As Integer, d As Integer
y = 2025
m = 12
d = 25
Dim christmas As Date
christmas = DateSerial(y, m, d)
' Current year's date
Dim thisYear As Date
thisYear = DateSerial(Year(Date), 1, 1) ' January 1 of current year</code></pre>
<h3 id="last-day-of-month">Last Day of Month</h3>
<pre><code class="language-vbnet">Function GetLastDayOfMonth(year As Integer, month As Integer) As Date
' Use day 0 of next month to get last day of current month
GetLastDayOfMonth = DateSerial(year, month + 1, 0)
End Function
' Usage
Dim lastDay As Date
lastDay = GetLastDayOfMonth(2025, 2) ' Feb 28, 2025 (or 29 in leap year)</code></pre>
<h3 id="first-day-of-month">First Day of Month</h3>
<pre><code class="language-vbnet">Function GetFirstDayOfMonth(someDate As Date) As Date
GetFirstDayOfMonth = DateSerial(Year(someDate), Month(someDate), 1)
End Function</code></pre>
<h2 id="common-patterns">Common Patterns</h2>
<h3 id="month-boundaries">Month Boundaries</h3>
<pre><code class="language-vbnet">Function GetMonthStart(someDate As Date) As Date
GetMonthStart = DateSerial(Year(someDate), Month(someDate), 1)
End Function
Function GetMonthEnd(someDate As Date) As Date
GetMonthEnd = DateSerial(Year(someDate), Month(someDate) + 1, 0)
End Function
' Get entire month range
Dim startDate As Date
Dim endDate As Date
startDate = GetMonthStart(Date)
endDate = GetMonthEnd(Date)</code></pre>
<h3 id="year-boundaries">Year Boundaries</h3>
<pre><code class="language-vbnet">Function GetYearStart(someDate As Date) As Date
GetYearStart = DateSerial(Year(someDate), 1, 1)
End Function
Function GetYearEnd(someDate As Date) As Date
GetYearEnd = DateSerial(Year(someDate), 12, 31)
End Function</code></pre>
<h3 id="quarter-boundaries">Quarter Boundaries</h3>
<pre><code class="language-vbnet">Function GetQuarterStart(year As Integer, quarter As Integer) As Date
Dim month As Integer
month = (quarter - 1) * 3 + 1
GetQuarterStart = DateSerial(year, month, 1)
End Function
Function GetQuarterEnd(year As Integer, quarter As Integer) As Date
Dim month As Integer
month = quarter * 3
GetQuarterEnd = DateSerial(year, month + 1, 0)
End Function</code></pre>
<h3 id="add-months-correctly">Add Months Correctly</h3>
<pre><code class="language-vbnet">Function AddMonths(startDate As Date, months As Integer) As Date
Dim y As Integer, m As Integer, d As Integer
y = Year(startDate)
m = Month(startDate)
d = Day(startDate)
' Add months (DateSerial handles overflow)
AddMonths = DateSerial(y, m + months, d)
End Function
' Handle day overflow gracefully
Function AddMonthsSafe(startDate As Date, months As Integer) As Date
Dim y As Integer, m As Integer, d As Integer
Dim lastDay As Date
y = Year(startDate)
m = Month(startDate)
d = Day(startDate)
' Get last day of target month
lastDay = DateSerial(y, m + months + 1, 0)
' Use smaller of original day or last day of month
If d > Day(lastDay) Then
d = Day(lastDay)
End If
AddMonthsSafe = DateSerial(y, m + months, d)
End Function</code></pre>
<h3 id="leap-year-detection">Leap Year Detection</h3>
<pre><code class="language-vbnet">Function IsLeapYear(year As Integer) As Boolean
Dim feb29 As Date
On Error Resume Next
feb29 = DateSerial(year, 2, 29)
IsLeapYear = (Err.Number = 0)
End Function</code></pre>
<h3 id="days-in-month">Days in Month</h3>
<pre><code class="language-vbnet">Function DaysInMonth(year As Integer, month As Integer) As Integer
Dim lastDay As Date
lastDay = DateSerial(year, month + 1, 0)
DaysInMonth = Day(lastDay)
End Function</code></pre>
<h3 id="birthday-this-year">Birthday This Year</h3>
<pre><code class="language-vbnet">Function GetBirthdayThisYear(birthDate As Date) As Date
GetBirthdayThisYear = DateSerial(Year(Date), Month(birthDate), Day(birthDate))
End Function
Function HasBirthdayPassed(birthDate As Date) As Boolean
HasBirthdayPassed = (GetBirthdayThisYear(birthDate) <= Date)
End Function</code></pre>
<h3 id="week-start-monday">Week Start (Monday)</h3>
<pre><code class="language-vbnet">Function GetWeekStart(someDate As Date) As Date
Dim offset As Integer
offset = Weekday(someDate, vbMonday) - 1
GetWeekStart = DateSerial(Year(someDate), Month(someDate), Day(someDate) - offset)
End Function</code></pre>
<h3 id="generate-date-range">Generate Date Range</h3>
<pre><code class="language-vbnet">Function GenerateMonthStarts(year As Integer) As Variant
Dim dates(1 To 12) As Date
Dim i As Integer
For i = 1 To 12
dates(i) = DateSerial(year, i, 1)
Next i
GenerateMonthStarts = dates
End Function</code></pre>
<h2 id="advanced-usage">Advanced Usage</h2>
<h3 id="fiscal-year-calculations">Fiscal Year Calculations</h3>
<pre><code class="language-vbnet">Function GetFiscalYearStart(calendarYear As Integer, fiscalStartMonth As Integer) As Date
GetFiscalYearStart = DateSerial(calendarYear, fiscalStartMonth, 1)
End Function
Function GetFiscalYearEnd(calendarYear As Integer, fiscalStartMonth As Integer) As Date
' Fiscal year end is day before next fiscal year starts
GetFiscalYearEnd = DateSerial(calendarYear + 1, fiscalStartMonth, 0)
End Function
Function GetCurrentFiscalYear(fiscalStartMonth As Integer) As Integer
Dim currentMonth As Integer
currentMonth = Month(Date)
If currentMonth >= fiscalStartMonth Then
GetCurrentFiscalYear = Year(Date)
Else
GetCurrentFiscalYear = Year(Date) - 1
End If
End Function</code></pre>
<h3 id="date-table-generator">Date Table Generator</h3>
<pre><code class="language-vbnet">Sub PopulateDateDimension(startYear As Integer, endYear As Integer)
Dim y As Integer, m As Integer, d As Integer
Dim currentDate As Date
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
' Open recordset...
For y = startYear To endYear
For m = 1 To 12
Dim daysInMonth As Integer
daysInMonth = Day(DateSerial(y, m + 1, 0))
For d = 1 To daysInMonth
currentDate = DateSerial(y, m, d)
rs.AddNew
rs("DateKey") = Format(currentDate, "yyyymmdd")
rs("FullDate") = currentDate
rs("Year") = y
rs("Quarter") = DatePart("q", currentDate)
rs("Month") = m
rs("Day") = d
rs("DayOfWeek") = Weekday(currentDate)
rs.Update
Next d
Next m
Next y
End Sub</code></pre>
<h3 id="anniversary-calculator">Anniversary Calculator</h3>
<pre><code class="language-vbnet">Function GetAnniversaryDate(originalDate As Date, yearsLater As Integer) As Date
Dim y As Integer, m As Integer, d As Integer
y = Year(originalDate)
m = Month(originalDate)
d = Day(originalDate)
GetAnniversaryDate = DateSerial(y + yearsLater, m, d)
End Function
' Handle Feb 29 anniversaries
Function GetAnniversaryDateSafe(originalDate As Date, yearsLater As Integer) As Date
Dim y As Integer, m As Integer, d As Integer
y = Year(originalDate) + yearsLater
m = Month(originalDate)
d = Day(originalDate)
' For Feb 29, use Feb 28 in non-leap years
If m = 2 And d = 29 Then
If Not IsLeapYear(y) Then
d = 28
End If
End If
GetAnniversaryDateSafe = DateSerial(y, m, d)
End Function</code></pre>
<h3 id="relative-date-builder">Relative Date Builder</h3>
<pre><code class="language-vbnet">Function BuildRelativeDate(baseDate As Date, yearOffset As Integer, _
monthOffset As Integer, dayOffset As Integer) As Date
BuildRelativeDate = DateSerial(Year(baseDate) + yearOffset, _
Month(baseDate) + monthOffset, _
Day(baseDate) + dayOffset)
End Function
' Get date 2 years, 3 months, and 5 days from now
Dim futureDate As Date
futureDate = BuildRelativeDate(Date, 2, 3, 5)</code></pre>
<h3 id="easter-calculation-simplified">Easter Calculation (Simplified)</h3>
<pre><code class="language-vbnet">Function GetEasterSunday(year As Integer) As Date
' Simplified Meeus/Jones/Butcher algorithm
Dim a As Integer, b As Integer, c As Integer
Dim d As Integer, e As Integer, f As Integer
Dim g As Integer, h As Integer, i As Integer
Dim k As Integer, l As Integer, m As Integer
Dim month As Integer, day As Integer
a = year Mod 19
b = year \ 100
c = year Mod 100
d = b \ 4
e = b Mod 4
f = (b + 8) \ 25
g = (b - f + 1) \ 3
h = (19 * a + b - d - g + 15) Mod 30
i = c \ 4
k = c Mod 4
l = (32 + 2 * e + 2 * i - h - k) Mod 7
m = (a + 11 * h + 22 * l) \ 451
month = (h + l - 7 * m + 114) \ 31
day = ((h + l - 7 * m + 114) Mod 31) + 1
GetEasterSunday = DateSerial(year, month, day)
End Function</code></pre>
<h3 id="business-month-end-handler">Business Month-End Handler</h3>
<pre><code class="language-vbnet">Function GetBusinessMonthEnd(year As Integer, month As Integer) As Date
Dim lastDay As Date
Dim dayOfWeek As Integer
lastDay = DateSerial(year, month + 1, 0)
dayOfWeek = Weekday(lastDay)
' If weekend, back up to Friday
If dayOfWeek = vbSaturday Then
lastDay = DateSerial(year, month + 1, -1) ' Friday
ElseIf dayOfWeek = vbSunday Then
lastDay = DateSerial(year, month + 1, -2) ' Friday
End If
GetBusinessMonthEnd = lastDay
End Function</code></pre>
<h3 id="date-validator">Date Validator</h3>
<pre><code class="language-vbnet">Function IsValidDate(year As Integer, month As Integer, day As Integer) As Boolean
On Error Resume Next
Dim testDate As Date
testDate = DateSerial(year, month, day)
IsValidDate = (Err.Number = 0) And _
(Year(testDate) = year) And _
(Month(testDate) = month) And _
(Day(testDate) = day)
End Function</code></pre>
<h2 id="error-handling">Error Handling</h2>
<pre><code class="language-vbnet">Function SafeDateSerial(year As Integer, month As Integer, day As Integer) As Variant
On Error GoTo ErrorHandler
' Validate ranges
If year < 100 Or year > 9999 Then
SafeDateSerial = Null
Exit Function
End If
SafeDateSerial = DateSerial(year, month, day)
Exit Function
ErrorHandler:
SafeDateSerial = Null
End Function</code></pre>
<h3 id="common-errors">Common Errors</h3>
<ul>
<li><strong>Error 5</strong> (Invalid procedure call): Year outside 100-9999 range</li>
<li><strong>Error 13</strong> (Type mismatch): Non-numeric arguments</li>
<li><strong>Error 6</strong> (Overflow): Result date outside valid range</li>
</ul>
<h2 id="performance-considerations">Performance Considerations</h2>
<ul>
<li><code>DateSerial</code> is very fast for date construction</li>
<li>More efficient than parsing date strings</li>
<li>Automatic range adjustment is performant</li>
<li>No string formatting overhead</li>
<li>Ideal for loop-based date generation</li>
</ul>
<h2 id="best-practices">Best Practices</h2>
<h3 id="use-for-date-construction">Use for Date Construction</h3>
<pre><code class="language-vbnet">' Good - Clear and unambiguous
deadline = DateSerial(2025, 12, 31)
' Avoid - Locale-dependent
deadline = CDate("12/31/2025") ' May fail in different locales</code></pre>
<h3 id="leverage-range-adjustment">Leverage Range Adjustment</h3>
<pre><code class="language-vbnet">' Use day 0 for last day of previous month
lastDayPrevMonth = DateSerial(year, month, 0)
' Use month 0 for last month of previous year
dec31 = DateSerial(year, 0, 31)</code></pre>
<h3 id="validate-before-critical-operations">Validate Before Critical Operations</h3>
<pre><code class="language-vbnet">If IsValidDate(y, m, d) Then
result = DateSerial(y, m, d)
Else
MsgBox "Invalid date components"
End If</code></pre>
<h3 id="extract-components-for-manipulation">Extract Components for Manipulation</h3>
<pre><code class="language-vbnet">' Extract, modify, rebuild
y = Year(someDate)
m = Month(someDate)
d = 1 ' First of month
newDate = DateSerial(y, m, d)</code></pre>
<h2 id="comparison-with-other-functions">Comparison with Other Functions</h2>
<h3 id="dateserial-vs-date-literals"><code>DateSerial</code> vs Date Literals</h3>
<pre><code class="language-vbnet">' DateSerial - Dynamic, programmatic
dt = DateSerial(Year(Date), 12, 25)
' Date Literal - Static, hardcoded
dt = #12/25/2025#</code></pre>
<h3 id="dateserial-vs-datevalue"><code>DateSerial</code> vs <code>DateValue</code></h3>
<pre><code class="language-vbnet">' `DateSerial` - From numeric components
dt = DateSerial(2025, 12, 25)
' `DateValue` - From string representation
dt = DateValue("December 25, 2025")</code></pre>
<h3 id="dateserial-vs-dateadd"><code>DateSerial</code> vs <code>DateAdd</code></h3>
<pre><code class="language-vbnet">' DateSerial - Absolute date construction
nextMonth = DateSerial(Year(Date), Month(Date) + 1, 1)
' DateAdd - Relative date calculation
nextMonth = DateAdd("m", 1, Date)</code></pre>
<h2 id="limitations">Limitations</h2>
<ul>
<li>Year must be between 100 and 9999</li>
<li>Two-digit year interpretation fixed (0-29=2000-2029, 30-99=1930-1999)</li>
<li>Always returns midnight (no time component)</li>
<li>Cannot directly specify time components</li>
<li>Invalid dates may raise runtime errors</li>
</ul>
<h2 id="related-functions">Related Functions</h2>
<ul>
<li><code>DateValue</code>: Converts a string to a date</li>
<li><code>TimeSerial</code>: Creates a time from hour, minute, and second</li>
<li><code>DateAdd</code>: Adds a time interval to a date</li>
<li><code>Year</code>, <code>Month</code>, <code>Day</code>: Extract date components</li>
<li><code>Date</code>: Returns current system date</li>
<li><code>Now</code>: Returns current date and time</li>
<li><code>IsDate</code>: Tests if a value can be converted to a date</li>
<li><code>CDate</code>: Converts an expression to a Date</li>
</ul>
</article>
<div style="margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--border-color);">
<p>
<a href="index.html">← Back to Datetime</a> |
<a href="../index.html">View all functions</a>
</p>
</div>
</main>
<footer>
<div class="container">
<p>© 2024-2026 VB6Parse Contributors. Licensed under the MIT License.</p>
</div>
</footer>
</body>
</html>