Time Tortoise: Daily Summary File, Part 2


This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.

This week’s task: an initial implementation of the Daily Summary File.


The DailySummary class is responsible for generating and writing the contents of the daily summary text file. It needs to know these things:

  • How often the file should be written.
  • How to retrieve the raw data that will be formatted in the file.
  • How to write a text file to disk.

This week’s code updates support those requirements.

Here’s the high-level design: MainViewModel contains an instance of DailySummary, and exposes a WriteDailySummary method. Other parts of the system call that method when they want to update the daily summary file.

The DailySummary class itself is part of the ViewModel project. It depends on Repository, which is part of Model. Think of the daily summary text file as a type of view, with the DailySummary class as the supporting view model.

Repository and IRepository

The Time Tortoise GUI shows a list of time segments for a selected activity, optionally filtered to a date range. For the daily summary, we want time segments filtered to the current day, but we want them for all activities, not just one. Rather than iterate through all activities, it’s more efficient to retrieve the required time segments in a single request. Entity Framework makes that easy. Here’s the Repository query:

return _context.TimeSegments.
Where(t => t.StartTime >= startTime.Value &&
t.EndTime <= endTime.Value).ToList();

Settings, ISettings, and SettingsUtility

The WriteDailySummary method uses a new setting, DailySummaryUpdateIntervalSeconds, to determine how often to update the summary file. If fewer seconds than specified have elapsed since the last update, then a call to WriteDailySummary has no effect.

With the Time Tortoise settings infrastructure, the following steps are used to add a new setting:

  • Add an accessor with the appropriate name to the ISettings interface and the Settings class.
  • Set a default value for the setting in the SetDefaultSettings method in SettingsUtility.
  • Add a section to settings.txt with the new setting name, its value, and a comment explaining the purpose of the setting.

I also made a change to SettingsUtility this week: the settings path is exposed as a public property, to make it easy for other classes (like DailySummary) to write files to the same location.


As explained in Time Tortoise: Timers, the view must own the main timer event in a UWP solution. To ensure that the daily summary file is updated periodically while the timer is running, the MainPage view calls Main.WriteDailySummary on each timer tick. But the file doesn’t actually get written on each tick, since WriteDailySummary checks the update interval setting first. It only gets updated as often as that setting specifies.

In addition to writing the file periodically while the timer is running, I also want to write it when the user starts and stops the timer. And there are other times (e.g., when the user edits a time segment) where it also makes sense to write the file. It’s easy enough to add more calls to WriteDailySummary to cover those cases.

Writing Text Files

Once all of the source data is available, the DailySummary class can write the file to disk. As explained in Time Tortoise: Reading and Writing Text Files in UWP Apps, UWP has some rules about file I/O and similar operations. However, it turns out that those rules aren’t enforced when a UWP app calls a method in a .NET Standard library from a UWP view. In that scenario, the File.WriteAllText method works as you would expect. So after building the summary file in memory (in a StringBuilder), I write it to disk by calling File.WriteAllText with the full path and the string representation of the file contents.

(Image credit: Kim Alaniz)