Using the following code with all the appropriate libraries imported. This is for a daily log post I'm creating in my lifelog.
period = datetime.today().date() - timedelta(days=1)
archive = zipfile.ZipFile("/Users/steven/Downloads/export.zip", "r")
df = pd.read_xml(
archive.open("apple_health_export/export.xml"),
xpath="//Record",
attrs_only=True,
parse_dates=["creationDate", "startDate", "endDate"],
)
d1 = df[
(df["endDate"].dt.date == period)
& (df["type"] == "HKQuantityTypeIdentifierHeartRate")
]
d1["value"] = [pd.to_numeric(x) for x in d1["value"]]
plt.style.use("ggplot")
plt.rcParams["font.family"] = "PT Sans"
d1.sort_values(by="endDate").plot(
x="endDate",
y="value",
xlabel="Time",
ylabel="Heart Rate (BPM)",
title="Heart Rate, Intraday",
).xaxis.set_major_formatter(mdates.DateFormatter("%-I:%M %p"))
plt.tight_layout()
plt.savefig(
f"/Users/steven/Library/Mobile Documents/com~apple~CloudDocs/Web/gloriouslyawkwardlife.github.io/images/{period}-heartrateintraday.png",
format="PNG",
)
The issue is that the plot is showing the times in the x-axis in UTC rather than EDT (GMT-4), even though the data coming in is also using EDT according to the sample below.
785810 HKQuantityTypeIdentifierHeartRateVariabilitySDNN Steven’s Apple Watch 11.1 ms ... 2024年11月01日 20:07:42-04:00 2024年11月01日 20:08:42-04:00 67.3322 <<HKDevice: 0x30005b660>, name:Apple Watch, ma...
785811 HKQuantityTypeIdentifierHeartRateVariabilitySDNN Steven’s Apple Watch 11.1 ms ... 2024年11月01日 22:06:15-04:00 2024年11月01日 22:07:15-04:00 26.4656 <<HKDevice: 0x30005b660>, name:Apple Watch, ma...
785812 HKQuantityTypeIdentifierHeartRateVariabilitySDNN Steven’s Apple Watch 11.1 ms ... 2024年11月02日 00:06:26-04:00 2024年11月02日 00:07:25-04:00 197.345 <<HKDevice: 0x30005b660>, name:Apple Watch, ma...
785813 HKQuantityTypeIdentifierHeartRateVariabilitySDNN Steven’s Apple Watch 11.1 ms ... 2024年11月02日 02:07:08-04:00 2024年11月02日 02:08:07-04:00 69.5713 <<HKDevice: 0x30005b660>, name:Apple Watch, ma...
785814 HKQuantityTypeIdentifierHeartRateVariabilitySDNN Steven’s Apple Watch 11.1 ms ... 2024年11月02日 04:06:10-04:00 2024年11月02日 04:07:10-04:00 89.6994 <<HKDevice: 0x30005b660>, name:Apple Watch, ma...
Finished plot showing times in wrong time zone
I tried doing an explicit time zone conversion as follows but it doesn't affect the end result:
df['endDate']=df['endDate'].dt.tz_convert(pytz.timezone('America/New_York'))
NOW, if I leave out the x-axis formatting (.xaxis.set_major_formatter(mdates.DateFormatter("%-I:%M %p"))), the times shown in the chart are showing in the proper time zone, but not in the format I prefer. See this image.
1 Answer 1
You can use mdates.DateFormatter with the correct time zone by setting tz directly in the formatted.
Here's the code:
formatter = mdates.DateFormatter("%-I:%M %p", tz=pytz.timezone("America/New_York"))
ax = d1.sort_values(by="endDate").plot(
x="endDate",
y="value",
xlabel="Time",
ylabel="Heart Rate (BPM)",
title="Heart Rate, Intraday",
)
ax.xaxis.set_major_formatter(formatter)
I hope this will help you a little.
2 Comments
pytz.timezone() may require using localize(). For python 3.9+, zoneinfo is a preferred option (stackoverflow.com/q/11473721/26993270).
matplotlib's default timezone or alternatively specifyingtz=when usingDateFormatter(). For nicer formatting trymdates.ConciseDateFormatter().tzis not explicitly stated inmdates.DateFormatter("%-I:%M %p")it takesUTC. More about theEST/EDTtimezone is here: stackoverflow.com/a/72793634/26993270