Bläddra i källkod

Improve countdown time handling

Daniel Chalmers 1 år sedan
förälder
incheckning
01a0b9066f

+ 19 - 0
DesktopClock.Tests/DateTimeTests.cs

@@ -42,6 +42,25 @@ public class DateTimeTests
         Assert.Equal(expected, result);
         Assert.Equal(expected, result);
     }
     }
 
 
+    [Theory]
+    [InlineData("2024-07-18T12:30:00Z", "2024-07-18T12:30:00Z", 60, true)] // Countdown reached
+    [InlineData("2024-07-18T12:29:00Z", "2024-07-18T12:30:00Z", 60, false)] // Not yet reached, not on interval
+    [InlineData("2024-07-18T12:30:30Z", "2024-07-18T12:30:01Z", 30, true)] // On interval
+    [InlineData("2024-07-18T12:30:01Z", "2024-07-18T12:30:00Z", 30, true)] // Countdown on interval
+    public void IsOnInterval(string dtString, string countdownToString, int intervalSeconds, bool expected)
+    {
+        // Arrange
+        var dateTime = DateTimeOffset.Parse(dtString);
+        var countdownTo = DateTimeOffset.Parse(countdownToString);
+        var interval = TimeSpan.FromSeconds(intervalSeconds);
+
+        // Act
+        var result = DateTimeUtil.IsOnInterval(dateTime, countdownTo, interval);
+
+        // Assert
+        Assert.Equal(expected, result);
+    }
+
     [Theory]
     [Theory]
     [InlineData("dddd, MMMM dd", "Monday, January 01")]
     [InlineData("dddd, MMMM dd", "Monday, January 01")]
     [InlineData("yyyy-MM-dd", "2024-01-01")]
     [InlineData("yyyy-MM-dd", "2024-01-01")]

+ 6 - 34
DesktopClock/MainWindow.xaml.cs

@@ -30,12 +30,6 @@ public partial class MainWindow : Window
     private SoundPlayer _soundPlayer;
     private SoundPlayer _soundPlayer;
     private PixelShifter _pixelShifter;
     private PixelShifter _pixelShifter;
 
 
-    /// <summary>
-    /// The date and time to countdown to, or <c>null</c> if regular clock is desired.
-    /// </summary>
-    [ObservableProperty]
-    private DateTimeOffset? _countdownTo;
-
     /// <summary>
     /// <summary>
     /// The current date and time in the selected time zone, or countdown as a formatted string.
     /// The current date and time in the selected time zone, or countdown as a formatted string.
     /// </summary>
     /// </summary>
@@ -54,7 +48,6 @@ public partial class MainWindow : Window
         DataContext = this;
         DataContext = this;
 
 
         _timeZone = Settings.Default.GetTimeZoneInfo();
         _timeZone = Settings.Default.GetTimeZoneInfo();
-        UpdateCountdownEnabled();
 
 
         Settings.Default.PropertyChanged += (s, e) => Dispatcher.Invoke(() => Settings_PropertyChanged(s, e));
         Settings.Default.PropertyChanged += (s, e) => Dispatcher.Invoke(() => Settings_PropertyChanged(s, e));
 
 
@@ -196,12 +189,12 @@ public partial class MainWindow : Window
                 break;
                 break;
 
 
             case nameof(Settings.Default.CountdownTo):
             case nameof(Settings.Default.CountdownTo):
-                UpdateCountdownEnabled();
                 UpdateTimeString();
                 UpdateTimeString();
                 break;
                 break;
 
 
             case nameof(Settings.Default.WavFilePath):
             case nameof(Settings.Default.WavFilePath):
             case nameof(Settings.Default.WavFileInterval):
             case nameof(Settings.Default.WavFileInterval):
+            case nameof(Settings.Default.PlaySoundOnCountdown):
                 UpdateSoundPlayerEnabled();
                 UpdateSoundPlayerEnabled();
                 break;
                 break;
         }
         }
@@ -219,20 +212,6 @@ public partial class MainWindow : Window
         TryPlaySound();
         TryPlaySound();
     }
     }
 
 
-    /// <summary>
-    /// Updates the countdown enabled state based on the settings.
-    /// </summary>
-    private void UpdateCountdownEnabled()
-    {
-        if (Settings.Default.CountdownTo == default)
-        {
-            CountdownTo = null;
-            return;
-        }
-
-        CountdownTo = Settings.Default.CountdownTo.ToDateTimeOffset(_timeZone.BaseUtcOffset);
-    }
-
     /// <summary>
     /// <summary>
     /// Initializes the sound player for the specified file if enabled; otherwise, sets it to <c>null</c>.
     /// Initializes the sound player for the specified file if enabled; otherwise, sets it to <c>null</c>.
     /// </summary>
     /// </summary>
@@ -240,7 +219,7 @@ public partial class MainWindow : Window
     {
     {
         var soundPlayerEnabled =
         var soundPlayerEnabled =
             !string.IsNullOrWhiteSpace(Settings.Default.WavFilePath) &&
             !string.IsNullOrWhiteSpace(Settings.Default.WavFilePath) &&
-            Settings.Default.WavFileInterval != default &&
+            (Settings.Default.WavFileInterval != default || Settings.Default.PlaySoundOnCountdown) &&
             File.Exists(Settings.Default.WavFilePath);
             File.Exists(Settings.Default.WavFilePath);
 
 
         _soundPlayer = soundPlayerEnabled ? new(Settings.Default.WavFilePath) : null;
         _soundPlayer = soundPlayerEnabled ? new(Settings.Default.WavFilePath) : null;
@@ -254,14 +233,7 @@ public partial class MainWindow : Window
         if (_soundPlayer == null)
         if (_soundPlayer == null)
             return;
             return;
 
 
-        // Whether we hit the interval specified in settings, which is calculated differently in countdown mode and not.
-        var isOnInterval = CountdownTo == null ?
-            (int)DateTimeOffset.Now.TimeOfDay.TotalSeconds % (int)Settings.Default.WavFileInterval.TotalSeconds == 0 :
-            (int)(CountdownTo.Value - DateTimeOffset.Now).TotalSeconds % (int)Settings.Default.WavFileInterval.TotalSeconds == 0;
-
-        var isCountdownReached = DateTimeOffset.Now.AreEqualExcludingMilliseconds(Settings.Default.CountdownTo);
-
-        if (!isOnInterval && !isCountdownReached)
+        if (!DateTimeUtil.IsOnInterval(DateTime.Now, Settings.Default.CountdownTo, Settings.Default.WavFileInterval))
             return;
             return;
 
 
         try
         try
@@ -294,16 +266,16 @@ public partial class MainWindow : Window
         {
         {
             var timeInSelectedZone = TimeZoneInfo.ConvertTime(DateTimeOffset.Now, _timeZone);
             var timeInSelectedZone = TimeZoneInfo.ConvertTime(DateTimeOffset.Now, _timeZone);
 
 
-            if (CountdownTo == null)
+            if (Settings.Default.CountdownTo == default)
             {
             {
                 return Tokenizer.FormatWithTokenizerOrFallBack(timeInSelectedZone, Settings.Default.Format, CultureInfo.DefaultThreadCurrentCulture);
                 return Tokenizer.FormatWithTokenizerOrFallBack(timeInSelectedZone, Settings.Default.Format, CultureInfo.DefaultThreadCurrentCulture);
             }
             }
             else
             else
             {
             {
                 if (string.IsNullOrWhiteSpace(Settings.Default.CountdownFormat))
                 if (string.IsNullOrWhiteSpace(Settings.Default.CountdownFormat))
-                    return CountdownTo.Humanize(timeInSelectedZone);
+                    return Settings.Default.CountdownTo.Humanize(utcDate: false, dateToCompareAgainst: DateTime.Now);
 
 
-                return Tokenizer.FormatWithTokenizerOrFallBack(Settings.Default.CountdownTo - timeInSelectedZone, Settings.Default.CountdownFormat, CultureInfo.DefaultThreadCurrentCulture);
+                return Tokenizer.FormatWithTokenizerOrFallBack(Settings.Default.CountdownTo - DateTime.Now, Settings.Default.CountdownFormat, CultureInfo.DefaultThreadCurrentCulture);
             }
             }
         }
         }
 
 

+ 11 - 0
DesktopClock/Utilities/DateTimeUtil.cs

@@ -48,4 +48,15 @@ public static class DateTimeUtil
 
 
         return true;
         return true;
     }
     }
+
+    public static bool IsOnInterval(DateTimeOffset dateTime, DateTimeOffset countdownTo, TimeSpan interval)
+    {
+        var currentTime = countdownTo == default ? dateTime.TimeOfDay : countdownTo - dateTime;
+
+        var isOnInterval = interval != default && (int)currentTime.TotalSeconds % (int)interval.TotalSeconds == 0;
+
+        var isCountdownReached = dateTime.AreEqualExcludingMilliseconds(countdownTo);
+
+        return isOnInterval || isCountdownReached;
+    }
 }
 }