[{"data":1,"prerenderedAt":348},["ShallowReactive",2],{"post:localizing-dates-mssql":3},{"id":4,"title":5,"body":6,"date":337,"description":12,"draft":338,"extension":339,"meta":340,"navigation":341,"path":342,"seo":343,"stem":344,"tags":345,"__hash__":347},"posts\u002Fposts\u002Flocalizing-dates-mssql.md","Localizing Dates In Sql Server",{"type":7,"value":8,"toc":330},"minimark",[9,13,18,34,69,72,96,100,115,118,121,158,161,165,176,201,216,219,230,309,313,326],[10,11,12],"p",{},"Several months ago I added timezone handling to a CF app. This post is my best effort to document how to localize dates using MSSQL timezone functionality.",[14,15,17],"h2",{"id":16},"retrieving-timezones-from-mssql","Retrieving Timezones from MSSQL",[10,19,20,21,28,29,33],{},"First, we need to know what time zones we can use. ",[22,23,27],"a",{"href":24,"rel":25},"https:\u002F\u002Fdocs.microsoft.com\u002Fen-us\u002Fsql\u002Frelational-databases\u002Fsystem-catalog-views\u002Fsys-time-zone-info-transact-sql?view=sql-server-2017",[26],"nofollow","MSSQL uses the Windows timezones as stored in the registry",", and they can be retrieved from the ",[30,31,32],"code",{},"sys.time_zone_info"," system view.",[35,36,41],"pre",{"className":37,"code":38,"language":39,"meta":40,"style":40},"language-sql shiki shiki-themes github-light github-dark","SELECT * FROM sys.time_zone_info\n","sql","",[30,42,43],{"__ignoreMap":40},[44,45,48,52,55,58,62,66],"span",{"class":46,"line":47},"line",1,[44,49,51],{"class":50},"szBVR","SELECT",[44,53,54],{"class":50}," *",[44,56,57],{"class":50}," FROM",[44,59,61],{"class":60},"sj4cs"," sys",[44,63,65],{"class":64},"sVt8B",".",[44,67,68],{"class":60},"time_zone_info\n",[10,70,71],{},"Do not try to interact with these time zones using a CFML timezone - the underlying Java timezones use a different timezone format and do not match the MSSQL\u002FWindows timezone format.",[10,73,74,75,79,80,83,84,87,88,91,92,95],{},"Also, you may notice that the timezone list ",[76,77,78],"em",{},"does not include different timezones for daylight saving time",". For example, there is a single timezone record for ",[30,81,82],{},"Eastern Standard Time",", or EST. ",[30,85,86],{},"Eastern Daylight Time"," is nowhere to be found, because this view automatically updates the ",[30,89,90],{},"current_utc_offset"," and ",[30,93,94],{},"is_currently_dst"," values based on the current time in that timezone.",[14,97,99],{"id":98},"retrieve-current-utc-offset-from-a-known-timezone","Retrieve Current UTC Offset From a Known Timezone",[10,101,102,103,107,108,110,111,114],{},"Next we use these time zones to get the ",[104,105,106],"strong",{},"current"," utc offset. Note I said ",[104,109,106],{}," - do ",[104,112,113],{},"not"," store the UTC offset, because it will change for a given time zone twice a year at minimum. (e.g. daylight saving time.)",[10,116,117],{},"For this reason, we'll need to store the user's time zone and retrieve the UTC offset when you need the user's local time.",[10,119,120],{},"Here's a simple way to retrieve the current UTC offset for a known time zone:",[35,122,124],{"className":37,"code":123,"language":39,"meta":40,"style":40},"SELECT current_utc_offset\nFROM sys.time_zone_info\nWHERE name='US Eastern Standard Time'\n",[30,125,126,133,145],{"__ignoreMap":40},[44,127,128,130],{"class":46,"line":47},[44,129,51],{"class":50},[44,131,132],{"class":64}," current_utc_offset\n",[44,134,136,139,141,143],{"class":46,"line":135},2,[44,137,138],{"class":50},"FROM",[44,140,61],{"class":60},[44,142,65],{"class":64},[44,144,68],{"class":60},[44,146,148,151,154],{"class":46,"line":147},3,[44,149,150],{"class":50},"WHERE",[44,152,153],{"class":50}," name=",[44,155,157],{"class":156},"sZZnC","'US Eastern Standard Time'\n",[10,159,160],{},"Obviously, in order to know which time zone to use you will need to allow the user to select their time zone so you can store that timezone with the user.",[14,162,164],{"id":163},"localize-dates-to-a-timezone-using-at-time-zone","Localize Dates To a Timezone Using AT TIME ZONE",[10,166,167,175],{},[22,168,171,172],{"href":169,"rel":170},"https:\u002F\u002Fdzone.com\u002Farticles\u002Fdates-and-times-in-sql-server-at-time-zone",[26],"Use ",[30,173,174],{},"AT TIME ZONE"," if you need to indicate the UTC offset of a datetime value:",[35,177,179],{"className":37,"code":178,"language":39,"meta":40,"style":40},"GETDATE() AT TIME ZONE 'US Eastern Standard Time'\n",[30,180,181],{"__ignoreMap":40},[44,182,183,186,189,192,195,198],{"class":46,"line":47},[44,184,185],{"class":60},"GETDATE",[44,187,188],{"class":64},"() ",[44,190,191],{"class":50},"AT",[44,193,194],{"class":50}," TIME",[44,196,197],{"class":50}," ZONE",[44,199,200],{"class":156}," 'US Eastern Standard Time'\n",[10,202,203,204,206,207,65],{},"Basically, this lets us select a date which was stored with no UTC offset and add a UTC offset to it - provided we know the original time zone. This paves the way for us to then convert the date from its original timezone - using ",[30,205,174],{}," - to another timezone - using ",[22,208,211,212,215],{"href":209,"rel":210},"https:\u002F\u002Fdatabase.guide\u002Fswitchoffset-examples-in-sql-server\u002F",[26],"the ",[30,213,214],{},"SWITCHOFFSET"," function",[14,217,214],{"id":218},"switchoffset",[10,220,221,222,225,226,229],{},"Once we have a ",[30,223,224],{},"DATETIMEOFFSET"," value, we can use ",[30,227,228],{},"SWITCHOFFSET(DATETIMEOFFSET, time_zone)"," to switch that datetime to match a user's local time:",[35,231,233],{"className":37,"code":232,"language":39,"meta":40,"style":40},"SWITCHOFFSET(\n    GETDATE() AT TIME ZONE 'US Eastern Standard Time',\n    (\n        SELECT current_utc_offset\n        FROM sys.time_zone_info\n        WHERE name='Central European Standard Time'\n    )\n)\n",[30,234,235,242,261,266,274,286,297,303],{"__ignoreMap":40},[44,236,237,239],{"class":46,"line":47},[44,238,214],{"class":60},[44,240,241],{"class":64},"(\n",[44,243,244,247,249,251,253,255,258],{"class":46,"line":135},[44,245,246],{"class":60},"    GETDATE",[44,248,188],{"class":64},[44,250,191],{"class":50},[44,252,194],{"class":50},[44,254,197],{"class":50},[44,256,257],{"class":156}," 'US Eastern Standard Time'",[44,259,260],{"class":64},",\n",[44,262,263],{"class":46,"line":147},[44,264,265],{"class":64},"    (\n",[44,267,269,272],{"class":46,"line":268},4,[44,270,271],{"class":50},"        SELECT",[44,273,132],{"class":64},[44,275,277,280,282,284],{"class":46,"line":276},5,[44,278,279],{"class":50},"        FROM",[44,281,61],{"class":60},[44,283,65],{"class":64},[44,285,68],{"class":60},[44,287,289,292,294],{"class":46,"line":288},6,[44,290,291],{"class":50},"        WHERE",[44,293,153],{"class":50},[44,295,296],{"class":156},"'Central European Standard Time'\n",[44,298,300],{"class":46,"line":299},7,[44,301,302],{"class":64},"    )\n",[44,304,306],{"class":46,"line":305},8,[44,307,308],{"class":64},")\n",[14,310,312],{"id":311},"conclusion","Conclusion",[10,314,315,316,321,322,325],{},"Unfortunately, this is not a full timezone localization writeup. Localization is very complex, and ",[22,317,320],{"href":318,"rel":319},"https:\u002F\u002Fjulianstodd.wordpress.com\u002F2011\u002F12\u002F21\u002Fthe-more-i-learn-the-less-i-know-learning-about-ignorance\u002F",[26],"the more I learn the less I know",". But hopefully this brief overview of timezone handling using built-in MSSQL functionality will come in useful for ",[76,323,324],{},"someone"," - enjoy!",[327,328,329],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":40,"searchDepth":135,"depth":135,"links":331},[332,333,334,335,336],{"id":16,"depth":135,"text":17},{"id":98,"depth":135,"text":99},{"id":163,"depth":135,"text":164},{"id":218,"depth":135,"text":214},{"id":311,"depth":135,"text":312},"2019-08-20T16:13:57-04:00",false,"md",{},true,"\u002Fposts\u002Flocalizing-dates-mssql",{"title":5,"description":12},"posts\u002Flocalizing-dates-mssql",[39,346],"localization","sl8esRXHd1olq97EP0GcgYYKAOjamV0f4SZTnASkI9s",1790471527763]