Forum Discussion
Dynamic User Time Zone Datetime Conversion in Power BI Embedded
- 7 months ago
Hello Nagaraj_D
Try these
Store all datetimes in UTC in the source and model.
Do NOT convert time zones in Power Query for multi-user embedded reports.
Use DAX-based conversion at visual/query time using:
Disconnected Dim_User_TimeZone
RLS or Embed token (per user)
DST logic in measures
Accept that measures can’t be used on slicers/axes.
If my response helped you, please consider clicking
Accept as Solution ✅ and giving it a Like 👍 – it helps others in the community too.
Thanks,
Connect with me on:
LinkedIn - 7 months ago
Hi Nagaraj_D ,
Thanks for posting this in the community and for clearly explaining your approach and the observations you made.
As already mentioned by mohit_sakhare and pankajnamekar25 in the earlier responses, keeping all datetimes in UTC and handling per user timezone conversion at query or visual time using DAX is the recommended pattern, with the known limitation that measures cannot be used on slicers or axes.
To specifically address the behavior you observed with the measure based datetime on drillthrough, this is expected. Measures do not define row level granularity in table or matrix visuals. When multiple underlying UTC rows evaluate to the same values for all visible columns and the datetime is provided only through a measure, Power BI groups those rows at render time. That is why the count is correct on the summary page, but the detail table can appear blank unless a physical column that preserves row uniqueness is present.
Including a unique identifier such as the call tracking ID, or keeping the original UTC datetime column for row grain and drillthrough while using the localized datetime measure only for display, is the correct and supported way to handle this.
Hope this helps. Please reach out for further assistance.
Thank you.
Hi — you’ve done a solid job exploring the two main patterns. The key thing to know is that per-user time zone conversion (especially with users changing time zones on the fly) can’t be modeled as a true “date column” in Import mode without some trade-off.
Here’s the clean guidance / best practice most of us recommend in this scenario:
1) Keep the model in UTC, do per-user conversion at query/visual time (DAX), not in Power Query
Your measure approach is the correct direction for “no refresh required” and for per-user behavior.
Yes, the limitation is real: a measure can’t be used as a slicer field or axis.
2) Don’t use Dynamic M Parameters for per-user time zone in a shared dataset
Dynamic M parameters are great for global parameterization, but they’re not meant for “each viewer gets their own parameter value”.
If the parameter value changes, it effectively changes the query behavior for the dataset/report, not isolated per viewer (so it’s risky in multi-user embedding).
3) Recommended workaround for slicers/axis: use a “local time dimension” + TREATAS pattern
Instead of trying to put the converted datetime itself on the axis:
Create a disconnected Date/Hour (or DateTime) dimension to use on slicers/axis (Day, Hour, Buckets, etc.)
In measures, compute the user’s offset/DST and then map UTC facts into the selected “local” buckets using TREATAS / virtual columns.
This is the typical approach used for “dynamic timezone by slicer/user” scenarios.
4) For your “hour bucket / overdue / <12hr / <24hr” scenarios
These should remain measures anyway:
Compute “now” in user local time (using the selected timezone offset)
Compute the difference in minutes/hours against the UTC timestamp adjusted to local
Return counts by bucket (the bucket table can be a small disconnected table used on axis)
Bottom line
If your #1 requirement is no refresh + per-user timezone that can change anytime, then DAX-at-render-time + disconnected axis tables is the most correct/maintainable approach.
Your Dynamic M / AT TIME ZONE approach is great for single-user or globally-set timezone, but it’s not the recommended pattern for multi-user embedded reports because parameterization isn’t truly per-user.
- Nagaraj_D7 months agoAdvocate I
Hi mohit_sakhare ,
Thanks for the detailed information.
I tested the shared dataset using the dynamic parameter approach in an embed scenario and confirmed that the DateTime columns are converted correctly based on the user’s time zone.
I will also try the approach you mentioned using a disconnected table and will share my observations afterward.
Regarding the measure-based approach, first thing is that I had hardcoded the time zone abbreviations [need more dynamic way of doing it.], and one more thing i forgot to metion earlier as I encountered a row count mismatch in a table visual.
For example:this is the table expected mbridn name addr caller calldate[utc] 101 ABC addr1 caller1 2025-10-01 10:30:00 AM 101 ABC addr1 caller1 2025-10-02 10:30:00 AM 101 ABC addr1 caller1 2025-10-03 10:30:00 AM example: in main page if i show the count as 3 and user will drillthrough from this count and navigate to detail report page but user will see blank table visual. if we use measure for calldate with timezone IST idn name addr caller calldate[measure] since all column values are same for that member in table visual shows blank. here instead if i try to bring utc column able to see all three rows. Currently added the distinct idn column in detail report page table visual and wrapped that column as user can't see but while export they can.I’d appreciate it if the community could share their thoughts or suggestions on this observation with the measure-based approach, and whether this behavior is expected or if there are recommended ways to handle it more effectively.
Thanks in advance!
- v-veshwara-msft7 months agoCommunity Support
Hi Nagaraj_D ,
Thanks for posting this in the community and for clearly explaining your approach and the observations you made.
As already mentioned by mohit_sakhare and pankajnamekar25 in the earlier responses, keeping all datetimes in UTC and handling per user timezone conversion at query or visual time using DAX is the recommended pattern, with the known limitation that measures cannot be used on slicers or axes.
To specifically address the behavior you observed with the measure based datetime on drillthrough, this is expected. Measures do not define row level granularity in table or matrix visuals. When multiple underlying UTC rows evaluate to the same values for all visible columns and the datetime is provided only through a measure, Power BI groups those rows at render time. That is why the count is correct on the summary page, but the detail table can appear blank unless a physical column that preserves row uniqueness is present.
Including a unique identifier such as the call tracking ID, or keeping the original UTC datetime column for row grain and drillthrough while using the localized datetime measure only for display, is the correct and supported way to handle this.
Hope this helps. Please reach out for further assistance.
Thank you.- v-veshwara-msft6 months agoCommunity Support
Hi Nagaraj_D ,
Just checking back to see if the explanation above helps clarify the behavior you observed with the measure based approach. Let us know if you have any follow up questions or if you’d like to explore alternative patterns further.Thank you.