DatePart
Extracts a specific component from a date value. Runtime-proven on a live Marketing Cloud Engagement CloudPage — including the fact that the hour comes back on a 12-hour clock with nothing to tell 7 AM from 7 PM.
Syntax
DatePart(dateString, datePart) → string
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
dateString |
string | date | Yes | A real date value or a parseable date string |
datePart |
string | Yes | One of Y, M, D, H, MI, year, month, monthName, day, hour or minute, in any capitalisation |
Example
%%[
VAR @when, @month
SET @when = "2026-03-04 09:05:07"
SET @month = DatePart(@when, "M")
]%%
%%=v(@month)=%%
Renders 03 — zero-padded, even though the hour from the same value comes back as a bare 9.
The long-form tokens are what make the function worth reaching for, because monthName has no other equivalent:
%%[
VAR @when, @name, @day, @year
SET @when = "2026-03-04 09:05:07"
SET @name = DatePart(@when, "monthName")
SET @day = DatePart(@when, "day")
SET @year = DatePart(@when, "year")
]%%
<p>%%=v(@name)=%% %%=v(@day)=%%, %%=v(@year)=%%</p>
Reach for FormatDate instead when you need the hour — see below.
Return value
string — the requested component as text: a four-digit year, a zero-padded two-digit month or day, an unpadded hour or minute, or the full English month name.
There is no closed set of sentinel values to test for, and no failure value either. Every rejected argument aborts the page with HTTP 422 rather than returning an error token, so a result that exists is always a real component.
Text does not mean the value needs converting first. Add(DatePart(@when, "Y"), 1) returned 2027 and Multiply(DatePart(@when, "M"), 10) returned 30 from a month that had rendered as 03, so the padding does not survive into arithmetic.
Behaviour
Eleven tokens are accepted, and they ignore case. The five abbreviations Y, M, D, H and MI work, and so do the long forms year, month, day, hour, minute and monthName. y, m, d, h, mi and Mi each returned exactly what their upper-case spelling returned, and YEAR, MONTHNAME and monthname all resolved. This is a wider set than the sibling DateAdd and DateDiff accept.
monthName is the only token with no abbreviation, and there is no day-name counterpart. It returned March for a date in March; a dayName token aborts the page, so the naming pattern does not generalise.
Anything else costs you the entire page. A seconds token in either spelling, a weeks token, a quarters token, a dayName token, an unknown two-letter token and an empty token string each returned HTTP 422 with no output at all, while a control call in the same deployment rendered normally. There is no seconds component available, so the finest resolution is the minute.
A date string and a real date value are interchangeable. ISO, ISO-T, US slash and spelled-out month forms all parsed, and the output of Now() and of DateAdd went straight in with no conversion. But an unparseable string, an empty string or a plain number aborts the page — the same unforgiving behaviour as DateAdd and DateDiff, and the opposite of FormatDate.
The padding is not uniform. From 2026-03-04 09:05:07 the month rendered 03 and the day 04, while the hour rendered 9 and the minute 5. Length() over the same calls gave 2 and 1. Concatenating parts therefore builds a ragged string rather than a fixed-width one. Full write-up in the differs-from-docs card.
The hour is a 12-hour clock
The hour is read off a twelve-hour clock and arrives without an AM/PM indicator, so the result is ambiguous by construction.
| Call | Renders |
|---|---|
DatePart("2026-11-23 19:35:47", "H") |
7 |
DatePart("2026-03-04 09:05:07", "H") |
9 |
DatePart("2026-03-04 00:30:00", "H") |
12 |
DatePart("2026-03-04 12:30:00", "H") |
12 |
DatePart("2026-03-04", "H") |
12 |
The last three rows are the ones that surprise: midnight is 12 rather than 0, and a date string with no time part at all is also 12 — so a missing time cannot be told apart from noon or from half past midnight. Anything that compares hours, buckets a send into a time of day, or feeds the number back into a date will be wrong for half the day. Use FormatDate with an HH pattern when a 24-hour value is needed, and treat this token as display-only. See the differs-from-docs card.
Show test script
%%[
VAR @b, @d1, @d2
SET @b = RequestParameter("b")
SET @d1 = "2026-03-04 09:05:07"
SET @d2 = "2026-11-23 19:35:47"
/* the control - fetch this whenever a branch below renders nothing */
IF @b == "ctrl" THEN
OutputLine(Concat("--- ctrl start ---"))
OutputLine(Concat("CTRL=[", DatePart(@d1, "Y"), "]"))
OutputLine(Concat("--- ctrl done ---"))
ENDIF
/* the five abbreviations, the 12-hour clock, the padding and arithmetic */
IF @b == "safe" THEN
OutputLine(Concat("--- safe start ---"))
OutputLine(Concat("P1Y=[", DatePart(@d1, "Y"), "]"))
OutputLine(Concat("P1M=[", DatePart(@d1, "M"), "]"))
OutputLine(Concat("P1D=[", DatePart(@d1, "D"), "]"))
OutputLine(Concat("P1H=[", DatePart(@d1, "H"), "]"))
OutputLine(Concat("P1MI=[", DatePart(@d1, "MI"), "]"))
OutputLine(Concat("P2Y=[", DatePart(@d2, "Y"), "]"))
OutputLine(Concat("P2M=[", DatePart(@d2, "M"), "]"))
OutputLine(Concat("P2D=[", DatePart(@d2, "D"), "]"))
OutputLine(Concat("P2H=[", DatePart(@d2, "H"), "]"))
OutputLine(Concat("P2MI=[", DatePart(@d2, "MI"), "]"))
OutputLine(Concat("LENM=[", Length(DatePart(@d1, "M")), "]"))
OutputLine(Concat("LENH=[", Length(DatePart(@d1, "H")), "]"))
OutputLine(Concat("ARITH=[", Add(DatePart(@d1, "Y"), 1), "]"))
OutputLine(Concat("ARITHM=[", Multiply(DatePart(@d1, "M"), 10), "]"))
OutputLine(Concat("MIDNIGHT=[", DatePart("2026-03-04 00:30:00", "H"), "]"))
OutputLine(Concat("NOON=[", DatePart("2026-03-04 12:30:00", "H"), "]"))
OutputLine(Concat("DATEONLY_H=[", DatePart("2026-03-04", "H"), "]"))
OutputLine(Concat("--- safe done ---"))
ENDIF
/* the six long-form tokens the official reference does not name */
IF @b == "longs" THEN
OutputLine(Concat("--- longs start ---"))
OutputLine(Concat("LYEAR=[", DatePart(@d1, "year"), "]"))
OutputLine(Concat("LMONTH=[", DatePart(@d1, "month"), "]"))
OutputLine(Concat("LMONTHNAME=[", DatePart(@d1, "monthName"), "]"))
OutputLine(Concat("LDAY=[", DatePart(@d1, "day"), "]"))
OutputLine(Concat("LHOUR=[", DatePart(@d2, "hour"), "]"))
OutputLine(Concat("LMINUTE=[", DatePart(@d1, "minute"), "]"))
OutputLine(Concat("--- longs done ---"))
ENDIF
/* the abbreviations ignore case */
IF @b == "case" THEN
OutputLine(Concat("--- case start ---"))
OutputLine(Concat("cY=[", DatePart(@d1, "y"), "]"))
OutputLine(Concat("cM=[", DatePart(@d1, "m"), "]"))
OutputLine(Concat("cD=[", DatePart(@d1, "d"), "]"))
OutputLine(Concat("cH=[", DatePart(@d2, "h"), "]"))
OutputLine(Concat("cMI=[", DatePart(@d1, "mi"), "]"))
OutputLine(Concat("cMi=[", DatePart(@d1, "Mi"), "]"))
OutputLine(Concat("--- case done ---"))
ENDIF
/* so do the long forms */
IF @b == "caselong" THEN
OutputLine(Concat("--- caselong start ---"))
OutputLine(Concat("cYEAR=[", DatePart(@d1, "YEAR"), "]"))
OutputLine(Concat("cMNAME=[", DatePart(@d1, "MONTHNAME"), "]"))
OutputLine(Concat("cmname=[", DatePart(@d1, "monthname"), "]"))
OutputLine(Concat("--- caselong done ---"))
ENDIF
/* date values and date strings are interchangeable */
IF @b == "dtype" THEN
OutputLine(Concat("--- dtype start ---"))
OutputLine(Concat("VALNOW=[", DatePart(Now(), "Y"), "]"))
OutputLine(Concat("VALADD=[", DatePart(DateAdd(@d1, 1, "D"), "D"), "]"))
OutputLine(Concat("ISO=[", DatePart("2026-03-04", "D"), "]"))
OutputLine(Concat("USSTR=[", DatePart("3/4/2026 9:05 AM", "D"), "]"))
OutputLine(Concat("WORDSTR=[", DatePart("4 March 2026", "M"), "]"))
OutputLine(Concat("ISOT=[", DatePart("2026-03-04T09:05:07", "MI"), "]"))
OutputLine(Concat("--- dtype done ---"))
ENDIF
/* each long form again in isolation, so none rides on a neighbour */
IF @b == "gyear" THEN
OutputLine(Concat("--- gyear start ---"))
OutputLine(Concat("GYEAR=[", DatePart(@d1, "year"), "]"))
OutputLine(Concat("--- gyear done ---"))
ENDIF
IF @b == "gmonth" THEN
OutputLine(Concat("--- gmonth start ---"))
OutputLine(Concat("GMONTH=[", DatePart(@d1, "month"), "]"))
OutputLine(Concat("--- gmonth done ---"))
ENDIF
IF @b == "gmname" THEN
OutputLine(Concat("--- gmname start ---"))
OutputLine(Concat("GMNAME=[", DatePart(@d1, "monthName"), "]"))
OutputLine(Concat("--- gmname done ---"))
ENDIF
IF @b == "gday" THEN
OutputLine(Concat("--- gday start ---"))
OutputLine(Concat("GDAY=[", DatePart(@d1, "day"), "]"))
OutputLine(Concat("--- gday done ---"))
ENDIF
IF @b == "ghour" THEN
OutputLine(Concat("--- ghour start ---"))
OutputLine(Concat("GHOUR=[", DatePart(@d2, "hour"), "]"))
OutputLine(Concat("--- ghour done ---"))
ENDIF
IF @b == "gminute" THEN
OutputLine(Concat("--- gminute start ---"))
OutputLine(Concat("GMINUTE=[", DatePart(@d1, "minute"), "]"))
OutputLine(Concat("--- gminute done ---"))
ENDIF
/* every branch below aborts the page - each renders NOTHING at all */
IF @b == "sec" THEN
OutputLine(Concat("--- sec start ---"))
OutputLine(Concat("SEC=[", DatePart(@d1, "S"), "]"))
ENDIF
IF @b == "seclong" THEN
OutputLine(Concat("--- seclong start ---"))
OutputLine(Concat("SECLONG=[", DatePart(@d1, "second"), "]"))
ENDIF
IF @b == "wk" THEN
OutputLine(Concat("--- wk start ---"))
OutputLine(Concat("WK=[", DatePart(@d1, "W"), "]"))
ENDIF
IF @b == "dayname" THEN
OutputLine(Concat("--- dayname start ---"))
OutputLine(Concat("DAYNAME=[", DatePart(@d1, "dayName"), "]"))
ENDIF
IF @b == "qt" THEN
OutputLine(Concat("--- qt start ---"))
OutputLine(Concat("QT=[", DatePart(@d1, "Q"), "]"))
ENDIF
IF @b == "bogus" THEN
OutputLine(Concat("--- bogus start ---"))
OutputLine(Concat("BOGUS=[", DatePart(@d1, "ZZ"), "]"))
ENDIF
IF @b == "emptytok" THEN
OutputLine(Concat("--- emptytok start ---"))
OutputLine(Concat("EMPTYTOK=[", DatePart(@d1, ""), "]"))
ENDIF
IF @b == "baddate" THEN
OutputLine(Concat("--- baddate start ---"))
OutputLine(Concat("BADDATE=[", DatePart("not a date at all", "Y"), "]"))
ENDIF
IF @b == "emptydate" THEN
OutputLine(Concat("--- emptydate start ---"))
OutputLine(Concat("EMPTYDATE=[", DatePart("", "Y"), "]"))
ENDIF
IF @b == "numdate" THEN
OutputLine(Concat("--- numdate start ---"))
OutputLine(Concat("NUMDATE=[", DatePart(20260304, "Y"), "]"))
ENDIF
IF @b == "a1" THEN
OutputLine(Concat("--- a1 start ---"))
OutputLine(Concat("A1=[", DatePart(@d1), "]"))
ENDIF
IF @b == "a3" THEN
OutputLine(Concat("--- a3 start ---"))
OutputLine(Concat("A3=[", DatePart(@d1, "Y", "extra"), "]"))
ENDIF
]%%
A bare string literal passed to OutputLine renders an empty line while the page still returns HTTP 200, so the marker silently vanishes and the block looks like a function that produced no output. Always wrap it — OutputLine(Concat("--- safe start ---")) — even for a single argument.
AMPscript has no try/catch, so a bad token or an unreadable date aborts the render and throws away everything already written above it. When testing, put each risky call behind its own RequestParameter branch and fetch them one at a time — otherwise a single failure hides every result on the page.
Availability
| Platform | Available |
|---|---|
| Marketing Cloud Engagement | Yes |
| Marketing Cloud Next | No |
Unlike Now, DateAdd, DateDiff and FormatDate, this function did not gain Marketing Cloud Next support in the Summer ‘26 release.
See also
- FormatDate — the way to get a 24-hour clock, a padded value, or a localised month name
- DateAdd · DateDiff — the sibling functions, whose token set is narrower
- Now — the value most often passed in
- The differs-from-docs cards — the 12-hour clock and the ragged padding
- Official reference · ampscript.guide