Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
7 years ago
Solved

Convert Date/Time in UTC to Local Time with Daylight savings

Hello,

 

I'm not sure where is the better place to do this manipulation, but I have a column with the date/time as following:

The time is in UTC and I want to convert this time to Mountain Daylight Time:

-between second Sunday of March and first Sunday of November you go back 6 hrs so UTC - 6

-between first Sunday of November and second Sunday of March you go back 7 hrs so UTC - 7

 

I found this article online that shows how to account for daylight savings on the refresh date: https://powerpivotpro.com/2019/01/dst-refresh-date-function-power-bi-service/

But I need to transform a column of data to the appropiate time. Is this possible? If it is, is it better to do in Power Query or Desktop of Power BI? Any help would be much appreciated.

 

Thank you.

 

  • Hi Anonymous ,

     

    I think there are many ways, for example I tried to find a pattern in order to catch the November first Sunday or March second Sunday, and for your specific needs, maybe this custom function could work:

     

    (datetimecolumn as datetime) =>
    
    let
    
    date = DateTime.Date(datetimecolumn),
    time = DateTime.Time(datetimecolumn),
    firstSundayOfNovember = Date.StartOfWeek(#date(Date.Year(date), 11, 7), Day.Sunday),
    SecondSundayOfMarch = Date.StartOfWeek(#date(Date.Year(date), 3, 14), Day.Sunday),
    
    isSummerTime =	(date = SecondSundayOfMarch and time >= #time(1,0,0))
    	        or
    		(date > SecondSundayOfMarch and date < firstSundayOfNovember) 
    		or 
    		(date = firstSundayOfNovember and time >= #time(1,0,0)),
    
    
    timeZone = (7 - Number.From(isSummerTime))*-1,
    
    MDT = 
                DateTime.From(date) 
                + #duration(0,Time.Hour(time),Time.Minute(time),Time.Second(time))  
                + #duration(0, timeZone, 0, 0)
    
    in
        MDT


    So for dates from March Second Sunday at 1:00am until November First Sunday at 12:59:59am you will get your datetime - 6 hours and for dates from November First Sunday 1:00am until March Second Sunday at 12:59:59am you will get your datetime - 7 hours

    According to Saint Google, the time is changed after 1:00am if you need it to be changed after 12:00am instead just remove first and last condition from isSummerTime

    If you have any question or if you find any error on the code, just let me know.

     

     

    Regards,

     

    Gian Carlo Poggi

     

     

  • gpoggi's avatar
    gpoggi
    7 years ago

    Sure Anonymous ,

     

    Right click on Queries pane and add a new Blank Query:

     

     

    Then right click on this new query and select Advanced Editor:

     

     

     

    In this new window erase all, paste the my code and click DONE:

     

     

     

    Now that query was converted into a function, you can rename it if you like, for example to "UTC_to_MDT":

     

     

     

    Then in order to use this function in your table you have different options, one option is going to your query or table, then click on Add Column / Invoke Custom Function, then put a name to this new column, select your function (in my case UTC_to_MDT) and select the column from your table you need to apply this function to (in my case "Date"):

     

     

     

    And then you will see the new date added :

     

     

     

    Hope this helps.

     

    Regards,

     

    Gian Carlo Poggi

61 Replies

  • gpoggi's avatar
    gpoggi
    Icon for Responsive Resident rankResponsive Resident

    Hi Anonymous ,

     

    I think there are many ways, for example I tried to find a pattern in order to catch the November first Sunday or March second Sunday, and for your specific needs, maybe this custom function could work:

     

    (datetimecolumn as datetime) =>
    
    let
    
    date = DateTime.Date(datetimecolumn),
    time = DateTime.Time(datetimecolumn),
    firstSundayOfNovember = Date.StartOfWeek(#date(Date.Year(date), 11, 7), Day.Sunday),
    SecondSundayOfMarch = Date.StartOfWeek(#date(Date.Year(date), 3, 14), Day.Sunday),
    
    isSummerTime =	(date = SecondSundayOfMarch and time >= #time(1,0,0))
    	        or
    		(date > SecondSundayOfMarch and date < firstSundayOfNovember) 
    		or 
    		(date = firstSundayOfNovember and time >= #time(1,0,0)),
    
    
    timeZone = (7 - Number.From(isSummerTime))*-1,
    
    MDT = 
                DateTime.From(date) 
                + #duration(0,Time.Hour(time),Time.Minute(time),Time.Second(time))  
                + #duration(0, timeZone, 0, 0)
    
    in
        MDT


    So for dates from March Second Sunday at 1:00am until November First Sunday at 12:59:59am you will get your datetime - 6 hours and for dates from November First Sunday 1:00am until March Second Sunday at 12:59:59am you will get your datetime - 7 hours

    According to Saint Google, the time is changed after 1:00am if you need it to be changed after 12:00am instead just remove first and last condition from isSummerTime

    If you have any question or if you find any error on the code, just let me know.

     

     

    Regards,

     

    Gian Carlo Poggi

     

     

    • Anonymous's avatar
      Anonymous
      Not applicable

      Thank you so much gpoggi  This works perfectly and it's also improved my understanding of custom functions in Power Query. My local time zone is NZST and being in the southern hemisphere our daylight savings spans the new year period, so I have to change the formula in isSummerTime slightly.

      (datetimecolumn as datetime) =>
      
      let
      date = DateTime.Date(datetimecolumn),
      time = DateTime.Time(datetimecolumn),
      
      lastSundayOfSeptember = Date.StartOfWeek(#date(Date.Year(date), 9, 30), Day.Sunday),
      firstSundayOfApril = Date.StartOfWeek(#date(Date.Year(date), 4, 7), Day.Sunday),
      
      isSummerTime =	
      		(date = lastSundayOfSeptember and time >= #time(2,0,0)) 
      	    or
      		(date > lastSundayOfSeptember) 
      		or
      		(date < firstSundayOfApril)  
      		or 
      		(date = firstSundayOfApril and time >= #time(3,0,0)), 
      
      timeZone = 12 + Number.From(isSummerTime), 
      										   
      NZST = 
                  DateTime.From(datetimecolumn) + #duration(0, timeZone, 0, 0) 														    
      in
          NZST

       

      • KarlOnEarth's avatar
        KarlOnEarth
        Frequent Visitor

        Hey thanks for posting that Anonymous , I used your mod to get Australian Eastern time and it works a treat.

    • freshwave's avatar
      freshwave
      Icon for Helper I rankHelper I

      Actually, below is a function that is even simpler than what has been posted here.  Someone on YouTube gave instructions how to create a column with a formula to add the TimeZone, and then selected to convert the time from Local to UTC.

       

      All I did was consolidate his logic into a simple function which you don't even need to worry about determining whether it is daylight savings time (DST) as Power BI already knows how to distinguish between it.  So like the function that was provided previously, you only need to add a column with the invoke function method and it will return the datetime in your local timezone.  I also added the ability for the function to accept nulls, as some of the columns I was working with are optional and aren't always populated.

       

      Hope this is helpful.

       

      The simple formula is:

       

      (datetimecolumn as nullable datetime) =>

       

      let

       

           DateTimeAddZone = DateTime.AddZone( datetimecolumn, 0 ),

           DateTimetoLocal = DateTimeZone.ToLocal( DateTimeAddZone ),

           DateTimeRemoveZone = DateTimeZone.RemoveZone( DateTimetoLocal ),

       

           UTC_To_Local = DateTimeRemoveZone

      //      UTC_To_Local = DateTimeZone.RemoveZone( DateTimeZone.ToLocal(DateTime.AddZone( datetimecolumn, 0 )))

       

      in

          UTC_To_Local

      • Anonymous's avatar
        Anonymous
        Not applicable

        Used this one to transfer from UTC over to AEST in Brisbane (Aus time). Worked a treat as is, thanks so much for this!

    • Anonymous's avatar
      Anonymous
      Not applicable

      gpoggi  thank you for the code, I understand the logic behind it and it should work. I am not sure how to create a function with the code and how to enable it to modify the column I want. Could you please provide step-by-step instructions? I am still new to the Power Query Editor. 

      • gpoggi's avatar
        gpoggi
        Icon for Responsive Resident rankResponsive Resident

        Sure Anonymous ,

         

        Right click on Queries pane and add a new Blank Query:

         

         

        Then right click on this new query and select Advanced Editor:

         

         

         

        In this new window erase all, paste the my code and click DONE:

         

         

         

        Now that query was converted into a function, you can rename it if you like, for example to "UTC_to_MDT":

         

         

         

        Then in order to use this function in your table you have different options, one option is going to your query or table, then click on Add Column / Invoke Custom Function, then put a name to this new column, select your function (in my case UTC_to_MDT) and select the column from your table you need to apply this function to (in my case "Date"):

         

         

         

        And then you will see the new date added :

         

         

         

        Hope this helps.

         

        Regards,

         

        Gian Carlo Poggi

  • Thanks for sharing this solution, it's pretty disappointing that PowerQuery doesn't have proper time zone support.

    I've tweaked it for conversion from UTC to UK time (aka Europe/London in tzdata)

     

    From When do the clocks change? - GOV.UK (www.gov.uk):


    In the UK the clocks go forward 1 hour at 1am on the last Sunday in March, and back 1 hour at 2am on the last Sunday in October.

    The period when the clocks are 1 hour ahead is called British Summer Time (BST). There’s more daylight in the evenings and less in the mornings (sometimes called Daylight Saving Time).

    When the clocks go back, the UK is on Greenwich Mean Time (GMT).


    datetime version:

     

    (datetimecolumn as datetime) =>
    
    let
    
    date = DateTime.Date(datetimecolumn),
    time = DateTime.Time(datetimecolumn),
    
    // From https://www.gov.uk/when-do-the-clocks-change
    // In the UK the clocks go forward 1 hour at 1am on the last Sunday in March,
    // and back 1 hour at 2am on the last Sunday in October.
    
    // Last Sunday in March
    ForwardDate = Date.StartOfWeek(#date(Date.Year(date), 3, 31), Day.Sunday),
    // Last Sunday in October
    BackDate = Date.StartOfWeek(#date(Date.Year(date), 10, 31), Day.Sunday),
    
    isSummerTime =
    		(date = ForwardDate and time >= #time(1,0,0))
    	    or
    		(date > ForwardDate and date < BackDate) 
    		or 
    		(date = BackDate and time < #time(1,0,0)),
    
    
    timeZone = Number.From(isSummerTime),
    
    Europe_London = datetimecolumn + #duration(0, timeZone, 0, 0)
    
    in
        Europe_London

     

     

    datetimezone version:

     

    let
        Source = (datetimecolumn as datetimezone) =>
    
    let
    
    // This version ignores the zone information in the input, but adds it to the output
    
    date = DateTime.Date(datetimecolumn),
    time = DateTime.Time(datetimecolumn),
    
    // From https://www.gov.uk/when-do-the-clocks-change
    // In the UK the clocks go forward 1 hour at 1am on the last Sunday in March,
    // and back 1 hour at 2am on the last Sunday in October.
    
    // Last Sunday in March
    ForwardDate = Date.StartOfWeek(#date(Date.Year(date), 3, 31), Day.Sunday),
    // Last Sunday in October
    BackDate = Date.StartOfWeek(#date(Date.Year(date), 10, 31), Day.Sunday),
    
    isSummerTime =
    		(date = ForwardDate and time >= #time(1,0,0))
    	    or
    		(date > ForwardDate and date < BackDate) 
    		or 
    		(date = BackDate and time < #time(1,0,0)),
    
    timeZone = Number.From(isSummerTime),
    
    Europe_London = DateTime.AddZone(DateTimeZone.RemoveZone(datetimecolumn) + #duration(0, timeZone, 0, 0) , timeZone)
    
    in
        Europe_London
    in
        Source

     

     

    I hope that's useful to someone!

    • Anonymous's avatar
      Anonymous
      Not applicable

      Hi Syndicate_Admin,

      You write "...and back 1 hour at 2am on the last Sunday in October", then there should be time < #time(2,0,0)) instead of time < #time(1,0,0)).

      (I had a similar error, I fixed it in my "UTC to CET" post.)

      • Syndicate_Admin's avatar
        Syndicate_Admin
        Icon for Administrator rankAdministrator

        No, because I'm converting from UTC to UK time. The "2 am" is in British Summer time, which is 01:00 UTC.

  • dax's avatar
    dax
    Icon for Community Support rankCommunity Support

    Hi bogdans,

    I will test this for you and inform you as soon as I get it . And you also could refer to this link for details.

    Best Regards,
    Zoe Zhi

    If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

  • Anonymous's avatar
    Anonymous
    Not applicable

    Hello, great solution!  However, I was getting "We couldn't authenticate with the credentails provided.  Please try again."  error after I refreshed the query.  My datasource is a SharePoint List and it showed that I was signed in but the credentails couldn't be autenticated.  The error went away after I removed the invoked function columns.  Any idea how to fix this?

     

  • Hey! I created this DAX formula to convert from UTC to PDT. Considering the following rules:

     

    Daylight Saving: Pacific Daylight Time (PDT) is a daylight saving/summer timezone, however during winter some places switch clocks for one hour back and observe Pacific Standard Time (PST).

     

     

    Start: Pacific Daylight Time (PDT) started on Sunday, March 14, 2021 at 2:00 am local time and clocks were set one hour forward to Sunday, March 14, 2021, 3:00 am. Daylight saving starts annually the on second Sunday of March

     

     

    End: Pacific Daylight Time (PDT) ends on Sunday, November 7, 2021 at 2:00 am local time and clocks are set one hour back to Sunday, November 7, 2021, 1:00 am local standard time instead. Daylight saving ends annually the on first Sunday of November

     

    UTC to PDT = 
    VAR CurrentDate = DATE(YEAR('Date'[Date]),MONTH('Date'[Date]),DAY('Date'[Date]))
    var CurrentTime = TIME(HOUR('Date'[Date]),MINUTE('Date'[Date]),SECOND('Date'[Date]))
    var March = DATE(2022,3,1)
    var November = DATE(2022,11,1)
    VAR SecondSundayMarch = FILTER(
            ALL('Date'[Date]),
            YEAR('Date'[Date]) = YEAR(CurrentDate) && 
            MONTH('Date'[Date]) = MONTH(March) && 
            DAY([Date]) > 7 && 
            DAY([Date]) < 15 && 
            WEEKDAY([Date],1) = 1)
    VAR FirstSundayNov = FILTER(
            ALL('Date'[Date]),
            YEAR('Date'[Date]) = YEAR(CurrentDate) && 
            MONTH('Date'[Date]) = MONTH(November) && 
            DAY([Date]) >= 1 && 
            DAY([Date]) < 8 && 
            WEEKDAY([Date],1) = 1)
    VAR IsSummerTime = OR(AND(CurrentDate = SecondSundayMarch, CurrentTime >= time(9,0,0)),  OR(AND(CurrentDate > SecondSundayMarch, CurrentDate < FirstSundayNov), AND(CurrentDate = FirstSundayNov, CurrentTime <= time(8,59,0))))
    VAR TimeDiff = TIME(8-IsSummerTime,0,0) // If is summer time diff = 7 else time diff = 8
    RETURN CurrentDate-TimeDiff

     

    • nehajadhav166's avatar
      nehajadhav166
      Icon for Resolver I rankResolver I

      Anonymous Can you please explain in steps more how do you used this formula?

      I have table with UTC timestamp. Is this formula needs to be created as measure in same table?

       

      Thanks,

      Neha

      • Anonymous's avatar
        Anonymous
        Not applicable

        Hi nehajadhav166 

        I've only used this in M in Power BI Services. 

        1. Create a custom function

        (datetimecolumn as datetime) =>
            let
            date = DateTime.Date(datetimecolumn),
            time = DateTime.Time(datetimecolumn),
            lastSundayOfOctober = Date.StartOfWeek(#date(Date.Year(date), 10, 31), Day.Sunday),
            lastSundayOfMarch = Date.StartOfWeek(#date(Date.Year(date), 3, 31), Day.Sunday),
            isSummerTime =	(date = lastSundayOfMarch and time >= #time(2,0,0))
            or
            (date > lastSundayOfMarch and date < lastSundayOfOctober)
            or
            (date = lastSundayOfOctober and time <= #time(2,0,0)),
            timeZone = 1 + Number.From(isSummerTime),
            CET =
            DateTime.From(date)
            + #duration(0,Time.Hour(time),Time.Minute(time),Time.Second(time))
            + #duration(0, timeZone, 0, 0)
        in
            CET

        2. Invoke custom function on the date column of your table to create a new column with the timestamp convertion

         

        I'm not able to provide you with a more detailed description at this point, and my screenshots are in Norwegian, but I hope this at least will help you a bit along the way.

         

         

  • I could't find a simple Dax for this so I came up with a pretty simple solution. This is UTS to Central with DLS.

     

    Adjusted Time UTC to Central =
    var _Year = year('Table'[DateTime])
    var _time = TIME(6,0,0)

    Var SundayNovemeber = CALCULATE(min('Table'[DateTime]), month('Table'[DateTime]) = 11, WEEKDAY('Table'[DateTime],1) = 1, YEAR('Table'[DateTime]) = _Year)
    Var SundayMarch = CALCULATE(min('Table'[DateTime]), month('Table'[DateTime]) = 3, WEEKDAY('Table'[DateTime],1) = 1, YEAR('Table'[DateTime]) = _Year)

    Var AdjustHours = if('Table'[DateTime]<=SundayMarch&& timevalue(format('Table'[DateTime], "hh:mm:ss")) < time(2,0,0) || 'Table'[DateTime] >= SundayNovemeber && timevalue(format('Table'[DateTime], "hh:mm:ss")) < time(2,0,0), 6, 5)

    Return
    'Table'[DateTime] - time(AdjustHours,0,0)
    • User5231's avatar
      User5231
      Icon for Helper II rankHelper II

      Var SundayMarch should actual be...

       

      Var SundayMarch = maxx(topn(2, Filter(DateTable, month(DateTable[Date]) = 3 && WEEKDAY(DateTable[Date],1) = 1 && YEAR(DateTable[Date]) = _Year), DateTable[Date] , ASC), [Date])
       
      I forgot March is the 2nd Sunday not the 1st