ASP.NET Core 6.0 - Client End Of Day
This article will describe how to visualize data using the client's end of day. I will assume you have downloaded the ASP.NET Core 6.0 - Homegrown Analytics Project.
Homegrown Analytics Project and Article Series
The Homegrown Analytics Project (HAP) is designed and organized to allow easy integration with existing projects. V2 simplifies the process with an Analytics area folder. The analytics schema can be implemented with SQL scripts or EF Core migration. See ASP.NET Core 6.0 - Analytics Schema and Integration. The HAP details page includes the version change log.
ASP.NET Core 6.0
- ASP.NET Core 6.0 - Homegrown Analytics
- ASP.NET Core 6.0 - Analytics Schema and Integration
- ASP.NET Core 6.0 - Data Collection
- ASP.NET Core 6.0 - Data Filters
- ASP.NET Core 6.0 - Data Visualization
- ASP.NET Core 6.0 - World Heat Map
- ASP.NET Core 6.0 - Homegrown TagHelpers
- ASP.NET Core 6.0 - Client End Of Day
ASP.NET Core 5.0
- ASP.NET Core 5.0 - Homegrown Analytics
- ASP.NET Core 5.0 - Analytics Schema and Integration
- ASP.NET Core 5.0 - Cookie Consent and GDPR
- ASP.NET Core 5.0 - Analytic Data Collection
- ASP.NET Core 5.0 - Not Found Errors
- ASP.NET Core 5.0 - Preferred UserAgents
- ASP.NET Core 5.0 - Analytic Dashboard
- ASP.NET Core 5.0 - Online User Count with SignalR
- ASP.NET Core 5.0 - Is Human with Google reCAPTCHA
- ASP.NET Core 5.0 - Log Maintenance with Hangfire
The HAP implements a Segments radio button group to query the data by the selected time interval where hour = 24 Hours, day = 7 Days, week = 5 Weeks, month = 6 months, and quarter = 4 Quarters. The last interval includes the latest data up to the selected view date. To calculate the start date time of the first interval, you need to calculate the end date time of the last interval. To calculate the end of the current hour, you can add 1 hour to a new DateTimeOffset derived from the current date time with 0 minutes and 0 seconds.
DateTimeOffset now = DateTimeOffset.UtcNow; DateTimeOffset endHour = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, 0, 0, TimeSpan.FromMinutes(0)).AddHours(1);
To calculate the end of the current day, you can add 1 day to a new DateTimeOffset derived from the current date time with 0 hours, 0 minutes, and 0 seconds.
DateTimeOffset now = DateTimeOffset.UtcNow; DateTimeOffset endDay = new DateTimeOffset(now.Year, now.Month, now.Day, 0, 0, 0, TimeSpan.FromMinutes(0)).AddDays(1);
The data is stored with a created DateTimeOffset property set to the UTC date and time. When 7 Days is selected, the segments and data are divided at midnight. If the TimeOffset cookie is found, the segments and data are divided by the client's midnight. The UTC and client date time format strings are set in AnalyticsSettings.cs.
public static string UtcDateTimeFormat { get; } = "{0:MM/dd/yy HH:mm} GMT"; public static string ClientDateTimeFormat { get; } = "{0:MM/dd/yy hh:mm tt}"; public static string UtcShortDateTimeFormat { get; } = "{0:M/d/yy HH:mm} GMT"; public static string ClientShortDateTimeFormat { get; } = "{0:M/d/yy h:mm tt}";
I developed a GetSegementsStartDateTimeOffset method in AnalyticsUtilities.cs which calculates the start date time of the first interval. When 5 Weeks is selected, the segments start on Sunday. I added a StartWeekOnMonday bool property to AnalyticsSettings to start on Monday rather than Sunday. To accurately calculate the client's end of week, month, and quarter you need to start with an accurate client's end of day. My hosting server is in the Pacific time zone and I develop in the Eastern time zone. I had to publish and test a couple of times before I got this right. The solution is set the offset parameter with the value from the TimeOffset cookie to a new DateTimeOffset variable.
public static DateTimeOffset GetSegementsStartDateTimeOffset(DateTimeOffset endTime, string segmentsFilter, double clientTimeOffset = 0) { DateTimeOffset startDateTimeOffset; DateTimeOffset endDay = endTime.AddMinutes(clientTimeOffset); endDay = new DateTimeOffset(endDay.Year, endDay.Month, endDay.Day, 0, 0, 0, TimeSpan.FromMinutes(clientTimeOffset)).AddDays(1); switch (segmentsFilter) { case "hour": DateTimeOffset endHour = endTime.AddMinutes(clientTimeOffset); endHour = new DateTimeOffset(endHour.Year, endHour.Month, endHour.Day, endHour.Hour, 0, 0, TimeSpan.FromMinutes(clientTimeOffset)).AddHours(1); startDateTimeOffset = endHour.AddHours(-24); break; case "day": startDateTimeOffset = endDay.AddDays(-7); break; case "week": DayOfWeek day = endDay.AddDays(-1).DayOfWeek; DateTimeOffset weekEnd = endDay.AddDays(-(day - DayOfWeek.Saturday) + (AnalyticsSettings.StartWeekOnMonday ? 1 : 0)); startDateTimeOffset = weekEnd.AddDays(-35); break; case "month": DateTimeOffset monthEnd = new DateTime(endDay.Year, endDay.Month, DateTime.DaysInMonth(endDay.Year, endDay.Month)); startDateTimeOffset = monthEnd.AddMonths(-6); break; case "quarter": int quarter = (endDay.Month + 2) / 3; DateTimeOffset quarterEnd = new DateTime(endDay.Year, 3 * quarter, 1).AddMonths(1); startDateTimeOffset = quarterEnd.AddYears(-1); break; default: DateTimeOffset endDefault = endTime.AddMinutes(clientTimeOffset); endDefault = new DateTimeOffset(endDefault.Year, endDefault.Month, endDefault.Day, endDefault.Hour, 0, 0, TimeSpan.FromMinutes(clientTimeOffset)).AddHours(1); startDateTimeOffset = endDefault.AddHours(-24); break; } return startDateTimeOffset; }
The images display the AnalyticsSampleData derived from a KenHaggerty.Com db backup.
Width
Live Demonstration
I publish the Users Without Passwords Project (UWPP) on the FIDO subdomain and the Users With Comments Project (UWCP) on the Preview subdomain. I integrated the HAP with the published projects. The subdomains have their own databases. Registered users can request permission to access the Admin - Analytics Dashboard. The permission will be granted automatically. The UWCP implements the Users With Device 2FA Project (UWD2FAP). Preview requires 2FA enabled to access admin pages.
After you register, browse to Manage Account > Visit Log. Click the More link in the HAP banner. Request permission.
Comments(0)