mirror of
https://github.com/duplicati/duplicati.git
synced 2025-11-28 03:20:25 +08:00
140 lines
6.4 KiB
C#
140 lines
6.4 KiB
C#
// Copyright (C) 2025, The Duplicati Team
|
|
// https://duplicati.com, hello@duplicati.com
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
// to deal in the Software without restriction, including without limitation
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
using System;
|
|
using System.Linq;
|
|
using Duplicati.Library.Utility;
|
|
using NUnit.Framework;
|
|
using Assert = NUnit.Framework.Legacy.ClassicAssert;
|
|
|
|
namespace Duplicati.UnitTest;
|
|
|
|
public class TimeZoneHelperTests : BasicSetupHelper
|
|
{
|
|
private static string CETName = OperatingSystem.IsWindows()
|
|
// For some reason CET is not recognized on Windows
|
|
// It has no effect outside the tests, as the string is not
|
|
// present outside the tests
|
|
? "Central European Standard Time"
|
|
: "CET";
|
|
|
|
[Test]
|
|
[Category("TimeZoneHelper")]
|
|
public void GetTimeZoneFromAbbreviationTest()
|
|
{
|
|
var timeZone = TimeZoneHelper.FindTimeZone("EST");
|
|
Assert.NotNull(timeZone);
|
|
|
|
timeZone = TimeZoneHelper.FindTimeZone("Pacific Standard Time");
|
|
Assert.NotNull(timeZone);
|
|
|
|
timeZone = TimeZoneHelper.FindTimeZone(CETName);
|
|
Assert.NotNull(timeZone);
|
|
}
|
|
|
|
[Test]
|
|
[Category("TimeZoneHelper")]
|
|
public void GetTimeZonesTest()
|
|
{
|
|
var timeZones = TimeZoneHelper.GetTimeZones();
|
|
Assert.That(timeZones.Any(x => x.CurrentUtcOffset.Hours == -5));
|
|
Assert.That(timeZones.Any(x => x.CurrentUtcOffset.Hours == -8));
|
|
Assert.That(timeZones.Any(x => x.CurrentUtcOffset.Hours == 1));
|
|
Assert.That(timeZones.Any(x => x.CurrentUtcOffset.Hours == 2));
|
|
}
|
|
|
|
[Test]
|
|
[Category("TimeZoneHelper")]
|
|
public void CheckTestSystemTimeZonesAreCorrect()
|
|
{
|
|
var timeZone = TimeZoneHelper.FindTimeZone(CETName);
|
|
var localTime = new DateTimeOffset(2024, 3, 31, 1, 59, 59, timeZone.BaseUtcOffset);
|
|
|
|
// Check that the system time is correct
|
|
Assert.AreEqual(1, timeZone.GetUtcOffset(localTime).Hours);
|
|
Assert.AreEqual(2, timeZone.GetUtcOffset(localTime.AddSeconds(2)).Hours);
|
|
}
|
|
|
|
[Test]
|
|
[Category("TimeZoneHelper")]
|
|
public void CheckRepeatScheduleIsStableOverDSTForward()
|
|
{
|
|
var timeZone = TimeZoneHelper.FindTimeZone(CETName);
|
|
var localTime = new DateTimeOffset(2024, 3, 30, 14, 0, 0, timeZone.BaseUtcOffset);
|
|
var localTimeOfDay = localTime.TimeOfDay;
|
|
|
|
var utcTime = localTime.ToUniversalTime().UtcDateTime;
|
|
|
|
var adjustedTimeSeconds = Timeparser.DSTAwareParseTimeInterval("2s", utcTime, timeZone);
|
|
var adjustedTimeHours = Timeparser.DSTAwareParseTimeInterval("1h", utcTime, timeZone);
|
|
var adjustedTimeDays = Timeparser.DSTAwareParseTimeInterval("1D", utcTime, timeZone);
|
|
|
|
// Non-day-based times are not corrected for DST
|
|
Assert.AreEqual(utcTime.AddSeconds(2), adjustedTimeSeconds);
|
|
Assert.AreEqual(utcTime.AddHours(1), adjustedTimeHours);
|
|
// Day-based times are corrected for DST
|
|
Assert.AreEqual(utcTime.AddDays(1).AddHours(-1), adjustedTimeDays);
|
|
|
|
// Since we adjust and keep the time of day, the time should be the same
|
|
var adjustedLocalTimeDays = TimeZoneInfo.ConvertTimeFromUtc(adjustedTimeDays, timeZone);
|
|
var adjustedLocalTimeOfDay = adjustedLocalTimeDays.TimeOfDay;
|
|
Assert.AreEqual(localTimeOfDay, adjustedLocalTimeOfDay);
|
|
|
|
// Since we adjust and keep the time of day, the time should be the same, even when going back
|
|
adjustedLocalTimeDays = TimeZoneInfo.ConvertTimeFromUtc(adjustedTimeDays, timeZone);
|
|
adjustedLocalTimeOfDay = adjustedLocalTimeDays.TimeOfDay;
|
|
Assert.AreEqual(localTimeOfDay, adjustedLocalTimeOfDay);
|
|
}
|
|
|
|
[Test]
|
|
[Category("TimeZoneHelper")]
|
|
public void CheckRepeatScheduleIsStableOverDSTBackward()
|
|
{
|
|
var timeZone = TimeZoneHelper.FindTimeZone(CETName);
|
|
var dstOffset = timeZone.GetUtcOffset(new DateTimeOffset(2024, 10, 26, 14, 0, 0, timeZone.BaseUtcOffset));
|
|
var localTime = new DateTimeOffset(2024, 10, 26, 14, 0, 0, dstOffset);
|
|
var crossTime = new DateTimeOffset(2024, 10, 27, 2, 59, 59, dstOffset);
|
|
var localTimeOfDay = localTime.TimeOfDay;
|
|
|
|
var utcTime = localTime.ToUniversalTime().UtcDateTime;
|
|
var utcCrossTime = crossTime.ToUniversalTime().UtcDateTime;
|
|
|
|
var adjustedTimeSeconds = Timeparser.DSTAwareParseTimeInterval("2s", utcCrossTime, timeZone);
|
|
var adjustedTimeHours = Timeparser.DSTAwareParseTimeInterval("1h", utcCrossTime, timeZone);
|
|
var adjustedTimeDays = Timeparser.DSTAwareParseTimeInterval("1D", utcTime, timeZone);
|
|
|
|
// Non-day-based times are not corrected for DST
|
|
Assert.AreEqual(utcCrossTime.AddSeconds(2), adjustedTimeSeconds);
|
|
Assert.AreEqual(utcCrossTime.AddHours(1), adjustedTimeHours);
|
|
// Day-based times are corrected for DST
|
|
Assert.AreEqual(utcTime.AddHours(1).AddDays(1), adjustedTimeDays);
|
|
|
|
// Since we adjust and keep the time of day, the time should be the same
|
|
var adjustedLocalTimeDays = TimeZoneInfo.ConvertTimeFromUtc(adjustedTimeDays, timeZone);
|
|
var adjustedLocalTimeOfDay = adjustedLocalTimeDays.TimeOfDay;
|
|
Assert.AreEqual(localTimeOfDay, adjustedLocalTimeOfDay);
|
|
|
|
// Since we adjust and keep the time of day, the time should be the same, even when going back
|
|
adjustedLocalTimeDays = TimeZoneInfo.ConvertTimeFromUtc(adjustedTimeDays, timeZone);
|
|
adjustedLocalTimeOfDay = adjustedLocalTimeDays.TimeOfDay;
|
|
Assert.AreEqual(localTimeOfDay, adjustedLocalTimeOfDay);
|
|
}
|
|
}
|