Aktualizace: Níže uvedená dokumentace byla aktualizována pro nový formát data 1.2. Získejte to hned!
Ačkoli JavaScript poskytuje spoustu metod pro získání a nastavení částí objektu data, chybí mu jednoduchý způsob formátování data a času podle uživatelem zadané masky. Existuje několik skriptů, které tuto funkci poskytují, ale nikdy jsem neviděl žádný, který by mi fungoval dobře... Většina z nich je zbytečně objemná nebo pomalá, spojuje nesouvisející funkce, používá komplikované syntaxe masek, které víceméně vyžadují, abyste si přečetli dokumentaci pokaždé, když je chcete použít, nebo nepočítejte se speciálními případy, jako jsou escapování znaků masky ve vygenerovaném řetězci.
Když jsem vybíral, které speciální znaky masky použít pro můj JavaScript formátovač data, podíval jsem se na funkci data PHP a diskrétní funkce dateFormat a timeFormat ColdFusion. PHP používá šílenou směs písmen (alespoň pro mě, protože nejsem PHP programátor) k reprezentaci různých datových entit, a i když si pravděpodobně nikdy nezapamatuji celý seznam, nabízí výhody, že můžete použít obojí. formátování data a času pomocí jedné funkce a žádný ze speciálních znaků se nepřekrývá (na rozdíl od ColdFusion, kde m
a mm
znamenají různé věci v závislosti na tom, zda máte co do činění s daty nebo časy). Na druhou stranu ColdFusion používá pro masky velmi snadno zapamatovatelné speciální znaky.
S mým formátovačem dat jsem se snažil vzít ty nejlepší vlastnosti z obou a přidat trochu vlastního cukru. Skončilo to hodně jako implementace ColdFusion, protože jsem primárně používal syntaxi masky CF.
Než se dostaneme k dalším podrobnostem, zde je několik příkladů, jak lze tento skript použít:
var now = new Date(); now.format("m/dd/yy"); // Returns, e.g., 6/09/07 // Can also be used as a standalone function dateFormat(now, "dddd, mmmm dS, yyyy, h:MM:ss TT"); // Saturday, June 9th, 2007, 5:46:21 PM // You can use one of several named masks now.format("isoDateTime"); // 2007-06-09T17:46:21 // ...Or add your own dateFormat.masks.hammerTime = 'HH:MM! "Can\'t touch this!"'; now.format("hammerTime"); // 17:46! Can't touch this! // When using the standalone dateFormat function, // you can also provide the date as a string dateFormat("Jun 9 2007", "fullDate"); // Saturday, June 9, 2007 // Note that if you don't include the mask argument, // dateFormat.masks.default is used now.format(); // Sat Jun 09 2007 17:46:21 // And if you don't include the date argument, // the current date and time is used dateFormat(); // Sat Jun 09 2007 17:46:22 // You can also skip the date argument (as long as your mask doesn't // contain any numbers), in which case the current date/time is used dateFormat("longTime"); // 5:46:22 PM EST // And finally, you can convert local time to UTC time. Either pass in // true as an additional argument (no argument skipping allowed in this case): dateFormat(now, "longTime", true); now.format("longTime", true); // Both lines return, e.g., 10:46:21 PM UTC // ...Or add the prefix "UTC:" to your mask. now.format("UTC:h:MM:ss TT Z"); // 10:46:21 PM UTC
Následují podporované speciální znaky. Jakékoli rozdíly ve významu od dateFormat
ColdFusion a timeFormat
funkce jsou zaznamenány.
Maska | Popis |
---|---|
d | Den v měsíci jako číslice; žádná úvodní nula pro jednociferné dny. |
dd | Den v měsíci jako číslice; úvodní nula pro jednociferné dny. |
ddd | Den v týdnu jako třípísmenná zkratka. |
dddd | Úplný název dne v týdnu. |
m | Měsíc jako číslice; žádná úvodní nula pro jednociferné měsíce. |
mm | Měsíc jako číslice; úvodní nula pro jednociferné měsíce. |
mmm | Měsíc jako třípísmenná zkratka. |
mmmm | Měsíc jako celý název. |
yy | Rok jako poslední dvě číslice; vedoucí nula pro roky menší než 10. |
yyyy | Rok reprezentovaný čtyřmi číslicemi. |
h | Hodiny; žádná úvodní nula pro jednociferné hodiny (12hodinový formát). |
hh | Hodiny; úvodní nula pro jednociferné hodiny (12hodinový formát). |
H | Hodiny; žádná úvodní nula pro jednociferné hodiny (24hodinový formát). |
HH | Hodiny; úvodní nula pro jednociferné hodiny (24hodinový formát). |
M | minuty; žádná úvodní nula pro jednociferné minuty. Velké M na rozdíl od CF timeFormat 's m se vyhnout konfliktu s měsíci. |
MM | minuty; úvodní nula pro jednociferné minuty. Velké MM na rozdíl od CF timeFormat 's mm, aby nedošlo ke konfliktu s měsíci. |
s | Sekundy; žádná úvodní nula pro jednociferné sekundy. |
ss | Sekundy; úvodní nula pro jednociferné sekundy. |
l nebo L | Milisekundy. l dává 3 číslice. L dává 2 číslice. |
t | Malý, jednoznakový řetězec časové značky:a nebo p . Žádný ekvivalent v CF. |
tt | Řetězec časové značky o dvou znacích malými písmeny:am nebo odpoledne . Žádný ekvivalent v CF. |
T | Řetězec časové značky tvořený velkými písmeny:A nebo P . Velké T na rozdíl od CF t umožňuje uživatelsky specifikovaná velká písmena. |
TT | Řetězec časové značky o dvou znacích velkými písmeny:AM nebo PM . Velká písmena TT na rozdíl od TT CF umožňují uživatelsky specifikovaná velká a malá písmena. |
Z | Zkratka časového pásma USA, např. EST nebo MDT . U časových pásem mimo USA nebo v prohlížeči Opera se posun GMT/UTC vrátí, např. GMT-0500 Žádný ekvivalent v CF. |
o | Posun časového pásma GMT/UTC, např. -0500 nebo +0230 . Žádný ekvivalent v CF. |
S | Řadová přípona data (st , nd , rd nebo th ). Funguje dobře s d .Žádný ekvivalent v CF. |
'…' nebo "…" | Doslovná sekvence znaků. Okolní uvozovky jsou odstraněny. Žádný ekvivalent v CF. |
UTC: | Musí to být první čtyři znaky masky. Před aplikací masky převede datum z místního času na čas UTC/GMT/Zulu. Předpona "UTC:" je odstraněna. Žádný ekvivalent v CF. |
A zde jsou pojmenované masky poskytované ve výchozím nastavení (můžete je snadno změnit nebo přidat vlastní):
Jméno | Maska | Příklad |
---|---|---|
výchozí | ddd mmm dd yyyy HH:MM:ss | So 9. června 2007 17:46:21 |
shortDate | m/d/rr | 6/9/07 |
střední Datum | d mmm, yyyy | 9. června 2007 |
longDate | d mmmm, yyyy | 9. června 2007 |
fullDate | dddd, mmmm d, yyyy | Sobota 9. června 2007 |
krátký čas | h:MM TT | 17:46 |
střední čas | h:MM:ss TT | 17:46:21 |
dlouhodobě | h:MM:ss TT Z | 17:46:21 EST |
isoDate | yyyy-mm-dd | 2007-06-09 |
isoTime | HH:MM:ss | 17:46:21 |
isoDateTime | yyyy-mm-dd'T'HH:MM:ss | 2007-06-09T17:46:21 |
isoUtcDateTime | UTC:yyyy-mm-dd'T'HH:MM:ss'Z' | 2007-06-09T22:46:21Z |
Pár problémů:
- V nepravděpodobném případě, že by význam vaší masky byl nejednoznačný (např.
m
následujemm
, bez oddělovacích znaků), vložte mezi své metasekvence pár prázdných uvozovek. Uvozovky budou automaticky odstraněny. - Pokud potřebujete do masky zahrnout doslovné uvozovky, platí následující pravidla:
- Nespárované nabídky nevyžadují zvláštní zacházení.
- Chcete-li do masek, které obsahují jakékoli jiné uvozovky stejného typu, zahrnout doslovné uvozovky, musíte je uzavřít alternativním typem uvozovek (tj. dvojité uvozovky pro jednoduché uvozovky a naopak). Např.
date.format('h "o\'clock, y\'all!"')
vrátí "6 hodin, všichni". Možná to může být trochu chlupaté, ale pochybuji, že se s tím lidé budou setkávat tak často. Předchozí příklad lze také zapsat jakodate.format("h") + "o'clock, y'all!"
.
Zde je kód:
/* * Date Format 1.2.3 * (c) 2007-2009 Steven Levithan <stevenlevithan.com> * MIT license * * Includes enhancements by Scott Trenda <scott.trenda.net> * and Kris Kowal <cixar.com/~kris.kowal/> * * Accepts a date, a mask, or a date and a mask. * Returns a formatted version of the given date. * The date defaults to the current date/time. * The mask defaults to dateFormat.masks.default. */ var dateFormat = function () { var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, timezoneClip = /[^-+\dA-Z]/g, pad = function (val, len) { val = String(val); len = len || 2; while (val.length < len) val = "0" + val; return val; }; // Regexes and supporting functions are cached through closure return function (date, mask, utc) { var dF = dateFormat; // You can't provide utc if you skip other args (use the "UTC:" mask prefix) if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { mask = date; date = undefined; } // Passing date through Date applies Date.parse, if necessary date = date ? new Date(date) : new Date; if (isNaN(date)) throw SyntaxError("invalid date"); mask = String(dF.masks[mask] || mask || dF.masks["default"]); // Allow setting the utc argument via the mask if (mask.slice(0, 4) == "UTC:") { mask = mask.slice(4); utc = true; } var _ = utc ? "getUTC" : "get", d = date[_ + "Date"](), D = date[_ + "Day"](), m = date[_ + "Month"](), y = date[_ + "FullYear"](), H = date[_ + "Hours"](), M = date[_ + "Minutes"](), s = date[_ + "Seconds"](), L = date[_ + "Milliseconds"](), o = utc ? 0 : date.getTimezoneOffset(), flags = { d: d, dd: pad(d), ddd: dF.i18n.dayNames[D], dddd: dF.i18n.dayNames[D + 7], m: m + 1, mm: pad(m + 1), mmm: dF.i18n.monthNames[m], mmmm: dF.i18n.monthNames[m + 12], yy: String(y).slice(2), yyyy: y, h: H % 12 || 12, hh: pad(H % 12 || 12), H: H, HH: pad(H), M: M, MM: pad(M), s: s, ss: pad(s), l: pad(L, 3), L: pad(L > 99 ? Math.round(L / 10) : L), t: H < 12 ? "a" : "p", tt: H < 12 ? "am" : "pm", T: H < 12 ? "A" : "P", TT: H < 12 ? "AM" : "PM", Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] }; return mask.replace(token, function ($0) { return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); }); }; }(); // Some common format strings dateFormat.masks = { "default": "ddd mmm dd yyyy HH:MM:ss", shortDate: "m/d/yy", mediumDate: "mmm d, yyyy", longDate: "mmmm d, yyyy", fullDate: "dddd, mmmm d, yyyy", shortTime: "h:MM TT", mediumTime: "h:MM:ss TT", longTime: "h:MM:ss TT Z", isoDate: "yyyy-mm-dd", isoTime: "HH:MM:ss", isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" }; // Internationalization strings dateFormat.i18n = { dayNames: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ] }; // For convenience... Date.prototype.format = function (mask, utc) { return dateFormat(this, mask, utc); };
Stáhněte si jej zde (1,2 kB při minifikaci a gzipování).
Upozorňujeme, že názvy dne a měsíce lze změnit (pro internacionalizaci nebo jiné účely) aktualizací dateFormat.i18n
objekt.
Pokud máte nějaké návrhy nebo najdete nějaké problémy, dejte mi vědět.
Chcete se dozvědět o afantazii a hyperfantazii, kultu Shen Yun nebo odhalování vůdkyně kultu Karen Zerby? Podívejte se na můj nový blog na Life After Tech.