├── packaging ├── _._ └── NodaTime.targets ├── NodaTime Release.snk ├── .gitattributes ├── NodaTime Release Public Key.snk ├── src ├── NodaTime │ ├── Calendars │ │ ├── Era.cs │ │ ├── IslamicEpoch.cs │ │ ├── EraCalculator.cs │ │ ├── CopticYearMonthDayCalculator.cs │ │ ├── JulianYearMonthDayCalculator.cs │ │ └── SingleEraCalculator.cs │ ├── TimeZones │ │ ├── Tzdb.nzd │ │ ├── TransitionMode.cs │ │ ├── IZoneIntervalMap.cs │ │ ├── SingleZoneIntervalMap.cs │ │ ├── InvalidDateTimeZoneSourceException.cs │ │ └── DateTimeZoneNotFoundException.cs │ ├── README.md │ ├── Annotations │ │ ├── FxCopAttributes.cs │ │ ├── MutableAttribute.cs │ │ ├── SpecialNullHandlingAttribute.cs │ │ ├── TestExemptionAttribute.cs │ │ ├── VisibleForTestingAttribute.cs │ │ ├── TrustedAttribute.cs │ │ └── ImmutableAttribute.cs │ ├── Globalization │ │ └── PatternResources.cs │ ├── Text │ │ ├── Delegates.cs │ │ ├── Patterns │ │ │ ├── IPatternParser.cs │ │ │ └── PatternBclSupport.cs │ │ ├── ParseBucket.cs │ │ ├── IPartialPattern.cs │ │ └── FixedFormatInfoPatternParser.cs │ ├── Fields │ │ ├── DatePeriodFields.cs │ │ ├── MonthsPeriodField.cs │ │ └── IDatePeriodField.cs │ ├── Utility │ │ └── ReferenceEqualityComparer.cs │ ├── Extensions │ │ ├── TimeOnlyExtensions.cs │ │ ├── DateOnlyExtensions.cs │ │ ├── IsoDayOfWeekExtensions.cs │ │ ├── DayOfWeekExtensions.cs │ │ ├── StopwatchExtensions.cs │ │ ├── DateTimeZoneProviderExtensions.cs │ │ ├── TimeSpanExtensions.cs │ │ └── DateTimeExtensions.cs │ ├── CalendarOrdinal.cs │ ├── IClock.cs │ ├── IsoDayOfWeek.cs │ ├── SystemClock.cs │ ├── AssemblyInfo.cs │ ├── TimeAdjusters.cs │ ├── NodaTime.csproj │ └── Xml │ │ └── XmlSerializationSettings.cs ├── NodaTime.Test │ ├── TestData │ │ ├── Tzdb2013bFromNodaTime1.1.nzd │ │ └── README │ ├── YearMonthTest.cs │ ├── GlobalUsings.cs │ ├── DateTimeZoneTest.Ids.cs │ ├── Calendars │ │ ├── WeekYearRulesTest.cs │ │ ├── EraTest.cs │ │ ├── IsoCalendarSystemTest.FieldValidation.cs │ │ ├── GregorianCalendarSystemTest.cs │ │ ├── JulianCalendarSystemTest.cs │ │ ├── HebrewEcclesiasticalCalculatorTest.cs │ │ └── IsoCalendarSystemTest.Era.cs │ ├── Extensions │ │ ├── TimeSpanExtensionsTest.cs │ │ ├── DateOnlyExtensionsTest.cs │ │ ├── TimeOnlyExtensionsTest.cs │ │ ├── StopwatchExtensionsTest.cs │ │ ├── DateTimeZoneProviderExtensionsTest.cs │ │ └── DateTimeOffsetExtensionsTest.cs │ ├── TimeZones │ │ ├── TzTestHelper.cs │ │ ├── IO │ │ │ └── TzdbStreamFieldTest.cs │ │ ├── TzdbDateTimeZoneTest.cs │ │ ├── TransitionTest.cs │ │ ├── EtcTest.cs │ │ ├── AlgiersTest.cs │ │ └── TimeZoneInfoReplacer.cs │ ├── Text │ │ ├── PatternNamingTest.cs │ │ ├── PeriodPatternTest.cs │ │ └── Patterns │ │ │ └── PatternFieldsExtensionsTest.cs │ ├── Ignore.cs │ ├── NamedWrapper.cs │ ├── TimeAdjustersTest.cs │ ├── Annotations │ │ ├── MutabilityTest.cs │ │ ├── SecurityTest.cs │ │ ├── PurityTest.cs │ │ ├── ReflectionTest.cs │ │ └── TrustedTest.cs │ ├── NodaConstantsTest.cs │ ├── SystemClockTest.cs │ ├── YearMonthTest.XmlSerialization.cs │ ├── CalendarSystemTest.Era.cs │ ├── Testing │ │ └── Extensions │ │ │ └── LocalDateConstructionTest.cs │ ├── YearMonthTest.BasicProperties.cs │ ├── coverageparams.xml │ ├── LocalTimeTest.Conversion.cs │ ├── Utility │ │ ├── TickArithmeticTest.cs │ │ └── BclConversionsTest.cs │ ├── ExceptionConstructorTests.cs │ ├── ConsistencyTest.cs │ ├── Xml │ │ └── XmlSchemaTest.XmlSchemaExporter.approved.xml │ ├── Globalization │ │ └── FailingCultureInfo.cs │ ├── CalendarSystemTest.cs │ ├── TypeInitializationTest.cs │ └── ZonedClockTest.cs ├── NodaTime.Tools.DumpTimeZoneInfo │ └── NodaTime.Tools.DumpTimeZoneInfo.csproj ├── NodaTime.AotCompatibilityTestApp │ ├── Program.cs │ └── NodaTime.AotCompatibilityTestApp.csproj ├── NodaTime.Tools.Common │ ├── NodaTime.Tools.Common.csproj │ └── FileUtility.cs ├── NodaTime.Tools.ValidateHistoricalNzd │ ├── NodaTime.Tools.ValidateHistoricalNzd.csproj │ └── Program.cs ├── NodaTime.Benchmarks.Custom │ ├── NodaTime.Benchmarks.Custom.csproj │ ├── ConfigurationException.cs │ ├── ConcurrentNoOp.cs │ ├── ConcurrentNewString.cs │ ├── ConcurrentToString.cs │ ├── ConcurrentPatternFormat.cs │ └── Program.cs ├── NodaTime.TzdbCompiler │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── NodaTime.TzdbCompiler.csproj │ └── Tzdb │ │ ├── MissingTokenException.cs │ │ └── IoExtensions.cs ├── NodaTime.Demo │ ├── GlobalUsings.cs │ ├── LocalTimeDemo.cs │ ├── NodaTime.Demo.csproj │ ├── PeriodBuilderDemo.cs │ ├── TimeAdjustersDemo.cs │ ├── LocalDateTimeDemo.cs │ ├── OffsetTimeDemo.cs │ ├── TimeZoneDemo.cs │ ├── AnnualDateDemo.cs │ └── InstantDemo.cs ├── NodaTime.TzdbCompiler.Test │ ├── GlobalUsings.cs │ ├── NodaTime.TzdbCompiler.Test.csproj │ └── Tzdb │ │ ├── RuleLineTest.cs │ │ └── DateTimeZoneBuilderTest.cs ├── NodaTime.NzdPrinter │ └── NodaTime.NzdPrinter.csproj ├── NodaTime.Testing │ ├── README.md │ ├── Preconditions.cs │ └── NodaTime.Testing.csproj ├── NodaTime.TzValidate.NzdCompatibility │ ├── NodaTime.TzValidate.NzdCompatibility.csproj │ ├── UserErrorException.cs │ └── Program.cs ├── NodaTime.TzValidate.NodaDump │ ├── NodaTime.TzValidate.NodaDump.csproj │ └── UserErrorException.cs └── NodaTime.Benchmarks │ ├── NodaTime.Benchmarks.csproj │ ├── Program.cs │ ├── NodaTimeTests │ ├── Calendars │ │ ├── SimpleWeekYearRuleBenchmarks.cs │ │ └── IsoCalendarBenchmarks.cs │ ├── ZoneYearOffsetBenchmarks.cs │ ├── BclDateTimeZoneBenchmarks.cs │ ├── Text │ │ ├── ZonedDateTimePatternBenchmarks.cs │ │ ├── LocalTimePatternBenchmarks.cs │ │ └── PeriodPatternBenchmarks.cs │ ├── PacificZonedDateTimeBenchmarks.cs │ ├── OffsetDateBenchmarks.cs │ ├── OffsetTimeBenchmarks.cs │ ├── DateIntervalBenchmarks.cs │ ├── UtcZonedDateTimeBenchmarks.cs │ └── StandardDaylightAlternatingMapBenchmarks.cs │ ├── CategoryAttribute.cs │ └── BclTests │ ├── UtcDateTimeBenchmarks.cs │ └── DateTimeOffsetBenchmarks.cs ├── global.json ├── data └── cldr │ └── readme.txt ├── NOTICE.txt ├── .github └── workflows │ ├── pull-request.yaml │ ├── push.yaml │ └── release.yaml ├── lib └── commandline │ ├── readme.txt │ └── LICENSE ├── Directory.Build.targets ├── AUTHORS.txt ├── README.md ├── Directory.Packages.props └── .gitignore /packaging/_._: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /NodaTime Release.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jskeet/nodatime/HEAD/NodaTime Release.snk -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | -------------------------------------------------------------------------------- /NodaTime Release Public Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jskeet/nodatime/HEAD/NodaTime Release Public Key.snk -------------------------------------------------------------------------------- /src/NodaTime/Calendars/Era.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jskeet/nodatime/HEAD/src/NodaTime/Calendars/Era.cs -------------------------------------------------------------------------------- /src/NodaTime/TimeZones/Tzdb.nzd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jskeet/nodatime/HEAD/src/NodaTime/TimeZones/Tzdb.nzd -------------------------------------------------------------------------------- /src/NodaTime.Test/TestData/Tzdb2013bFromNodaTime1.1.nzd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jskeet/nodatime/HEAD/src/NodaTime.Test/TestData/Tzdb2013bFromNodaTime1.1.nzd -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/global", 3 | "sdk": { 4 | "version": "8.0.100", 5 | "allowPrerelease": false, 6 | "rollForward": "latestMinor" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/NodaTime.Tools.DumpTimeZoneInfo/NodaTime.Tools.DumpTimeZoneInfo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net8.0 5 | 6 | 7 | -------------------------------------------------------------------------------- /data/cldr/readme.txt: -------------------------------------------------------------------------------- 1 | Note that the file format for Windows mappings changed around CLDR 2.0.1 2 | to include a territory ID. Earlier versions have been removed as no longer 3 | being valid for the code base which now expects the more complete mapping 4 | information. 5 | -------------------------------------------------------------------------------- /src/NodaTime/README.md: -------------------------------------------------------------------------------- 1 | Noda Time is an alternative date and time API for .NET. It helps you to 2 | think about your data more clearly, and express operations on that data more 3 | precisely. 4 | 5 | See the project web site at https://nodatime.org for more details. 6 | -------------------------------------------------------------------------------- /src/NodaTime.AotCompatibilityTestApp/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | Console.WriteLine("This app is purely for AOT publication testing."); 5 | -------------------------------------------------------------------------------- /src/NodaTime.Tools.Common/NodaTime.Tools.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/NodaTime.Tools.ValidateHistoricalNzd/NodaTime.Tools.ValidateHistoricalNzd.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks.Custom/NodaTime.Benchmarks.Custom.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net471;net6.0;net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/NodaTime.Test/YearMonthTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime.Test 6 | { 7 | // Just a container file for the partial class that's filled in by the nested source files. 8 | public partial class YearMonthTest 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/NodaTime.TzdbCompiler/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using System.Runtime.CompilerServices; 7 | 8 | [assembly: CLSCompliant(true)] 9 | [assembly: InternalsVisibleTo("NodaTime.TzdbCompiler.Test" + NodaTime.Properties.AssemblyInfo.PublicKeySuffix)] 10 | -------------------------------------------------------------------------------- /src/NodaTime.Demo/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // See https://docs.nunit.org/articles/nunit/release-notes/Nunit4.0-MigrationGuide.html 2 | global using Assert = NUnit.Framework.Legacy.ClassicAssert; 3 | global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; 4 | global using StringAssert = NUnit.Framework.Legacy.StringAssert; 5 | global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; 6 | global using FileAssert = NUnit.Framework.Legacy.FileAssert; 7 | -------------------------------------------------------------------------------- /src/NodaTime.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // See https://docs.nunit.org/articles/nunit/release-notes/Nunit4.0-MigrationGuide.html 2 | global using Assert = NUnit.Framework.Legacy.ClassicAssert; 3 | global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; 4 | global using StringAssert = NUnit.Framework.Legacy.StringAssert; 5 | global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; 6 | global using FileAssert = NUnit.Framework.Legacy.FileAssert; 7 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | ============================================================================= 2 | = NOTICE file corresponding to section 4d of the Apache License Version 2.0 = 3 | ============================================================================= 4 | This product includes ports of software developed by 5 | Joda.org (http://www.joda.org/). 6 | 7 | (Portions of Noda Time were derived from Joda Time 1.6.0; Joda Time 8 | 1.6.0 is copyright 2001-2009 Stephen Colebourne.) 9 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks.Custom/ConfigurationException.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime.Benchmarks.Custom; 8 | 9 | internal class ConfigurationException : Exception 10 | { 11 | internal ConfigurationException(string message) : base(message) 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NodaTime.TzdbCompiler.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // See https://docs.nunit.org/articles/nunit/release-notes/Nunit4.0-MigrationGuide.html 2 | global using Assert = NUnit.Framework.Legacy.ClassicAssert; 3 | global using CollectionAssert = NUnit.Framework.Legacy.CollectionAssert; 4 | global using StringAssert = NUnit.Framework.Legacy.StringAssert; 5 | global using DirectoryAssert = NUnit.Framework.Legacy.DirectoryAssert; 6 | global using FileAssert = NUnit.Framework.Legacy.FileAssert; 7 | -------------------------------------------------------------------------------- /src/NodaTime.TzdbCompiler/NodaTime.TzdbCompiler.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/NodaTime.NzdPrinter/NodaTime.NzdPrinter.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | Exe 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/NodaTime.Testing/README.md: -------------------------------------------------------------------------------- 1 | Noda Time is an alternative date and time API for .NET. It helps you to 2 | think about your data more clearly, and express operations on that data more 3 | precisely. 4 | 5 | The `NodaTime.Testing` package is designed to work with the 6 | `NodaTime` package, providing fakes for `IClock` and time zones, as 7 | well as extension methods to construct values for tests in a fluent 8 | manner. 9 | 10 | See the project web site at https://nodatime.org for more details. 11 | -------------------------------------------------------------------------------- /src/NodaTime.TzValidate.NzdCompatibility/NodaTime.TzValidate.NzdCompatibility.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net48 4 | Exe 5 | disable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/NodaTime.Test/TestData/README: -------------------------------------------------------------------------------- 1 | This directory contains the following files, used by various test cases. 2 | 3 | Tzdb2013bFromNodaTime1.1.nzd 4 | TZDB 2013b, as distributed with Noda Time 1.1 (in NodaZoneData format). 5 | A test verifies that we can read and use the file's contents using the 6 | current version of the stream parser. 7 | 8 | LinuxAdjustmentRuleTestData.txt 9 | Data for TimeZoneInfo.AdjustmentRule on Linux (.NET Core 3.1 and .NET 6) 10 | for use in BclDateTimeZoneTest.LinuxAdjustmentRules. 11 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yaml: -------------------------------------------------------------------------------- 1 | name: Build pull request 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | 7 | build: 8 | runs-on: ubuntu-latest 9 | env: 10 | DOTNET_NOLOGO: true 11 | 12 | steps: 13 | - uses: actions/checkout@v3 14 | with: 15 | submodules: true 16 | 17 | - name: Setup .NET 18 | uses: actions/setup-dotnet@v3 19 | with: 20 | dotnet-version: | 21 | 6.0.x 22 | 8.0.x 23 | 24 | - name: Build and test 25 | run: | 26 | build/ci.sh 27 | -------------------------------------------------------------------------------- /src/NodaTime.TzValidate.NodaDump/NodaTime.TzValidate.NodaDump.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/NodaTime.TzdbCompiler.Test/NodaTime.TzdbCompiler.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /lib/commandline/readme.txt: -------------------------------------------------------------------------------- 1 | The Command Line Parser Library is hosted at 2 | https://github.com/gsscoder/commandline 3 | 4 | We build the source files into NodaTime.TzdbCompiler, to avoid requiring a 5 | strongly-named copy of the assembly. Please see the LICENSE file 6 | for further information. We don't anticipate any need to keep this 7 | library particularly up-to-date, and it's not currently included in the 8 | binaries distributed with Noda Time. 9 | 10 | Modification 11 | ------------ 12 | 13 | This copy of the library has been modified to be compatible with 14 | .NET Core. -------------------------------------------------------------------------------- /src/NodaTime/Annotations/FxCopAttributes.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | // This file just contains attributes that FxCop understands. 8 | // This is partly to work around https://github.com/dotnet/roslyn-analyzers/issues/3451 9 | 10 | namespace NodaTime.Annotations 11 | { 12 | [AttributeUsage(AttributeTargets.Parameter)] 13 | internal sealed class ValidatedNotNullAttribute : Attribute { } 14 | } 15 | -------------------------------------------------------------------------------- /src/NodaTime.TzValidate.NodaDump/UserErrorException.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime.TzValidate.NodaDump 8 | { 9 | /// 10 | /// An exception caused by user error, e.g. invalid options. 11 | /// 12 | public sealed class UserErrorException : Exception 13 | { 14 | public UserErrorException(string message) : base(message) 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/NodaTime/Annotations/MutableAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime.Annotations 8 | { 9 | /// 10 | /// Indicates that a type is mutable. Some members of this type 11 | /// allow state to be visibly changed. 12 | /// 13 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] 14 | internal sealed class MutableAttribute : Attribute 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NodaTime.TzValidate.NzdCompatibility/UserErrorException.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime.TzValidate.NzdCompatibility 8 | { 9 | /// 10 | /// An exception caused by user error, e.g. invalid options. 11 | /// 12 | public sealed class UserErrorException : Exception 13 | { 14 | public UserErrorException(string message) : base(message) 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/NodaTime.Demo/LocalTimeDemo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.Globalization; 6 | using NUnit.Framework; 7 | 8 | namespace NodaTime.Demo 9 | { 10 | public class LocalTimeDemo 11 | { 12 | [Test] 13 | public void Construction() 14 | { 15 | LocalTime time = Snippet.For(new LocalTime(16, 20, 0)); 16 | Assert.AreEqual("16:20:00", time.ToString("HH:mm:ss", CultureInfo.InvariantCulture)); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/push.yaml: -------------------------------------------------------------------------------- 1 | name: Build push 2 | 3 | # TODO in the future: 4 | # - Run on Windows 5 | # - Coverage 6 | 7 | on: 8 | push: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | 14 | build: 15 | runs-on: ubuntu-latest 16 | env: 17 | DOTNET_NOLOGO: true 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | with: 22 | submodules: true 23 | 24 | - name: Setup .NET 25 | uses: actions/setup-dotnet@v3 26 | with: 27 | dotnet-version: | 28 | 6.0.x 29 | 8.0.x 30 | 31 | - name: Build and test 32 | run: | 33 | build/ci.sh 34 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTime.Benchmarks.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net48;net8.0 5 | Exe 6 | latest 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/NodaTime/Globalization/PatternResources.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.Resources; 6 | 7 | namespace NodaTime.Globalization 8 | { 9 | /// 10 | /// Takes the place of the designer-generated code for PatternResources.resx 11 | /// 12 | static class PatternResources 13 | { 14 | internal static ResourceManager ResourceManager { get; } 15 | = new ResourceManager(typeof(PatternResources).FullName!, typeof(PatternResources).Assembly); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NodaTime.Test/DateTimeZoneTest.Ids.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | 7 | namespace NodaTime.Test 8 | { 9 | /// 10 | /// Tests for code in DateTimeZone and code which will be moving out 11 | /// of DateTimeZones into DateTimeZone over time. 12 | /// 13 | public partial class DateTimeZoneTest 14 | { 15 | [Test] 16 | public void UtcIsNotNull() 17 | { 18 | Assert.IsNotNull(DateTimeZone.Utc); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NodaTime/Text/Delegates.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Text.Patterns; 6 | 7 | namespace NodaTime.Text 8 | { 9 | // This file contains all the delegates declared within the NodaTime.Text namespace. 10 | // It's simpler than either nesting them or giving them a file per delegate. 11 | internal delegate void CharacterHandler 12 | (PatternCursor patternCursor, SteppedPatternBuilder patternBuilder) 13 | where TBucket : ParseBucket; 14 | } 15 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)')) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Calendars/WeekYearRulesTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Calendars; 6 | using NUnit.Framework; 7 | using System; 8 | using System.Globalization; 9 | 10 | namespace NodaTime.Test.Calendars 11 | { 12 | public class WeekYearRulesTest 13 | { 14 | [Test] 15 | public void UnsupportedCalendarWeekRule() 16 | { 17 | Assert.Throws(() => WeekYearRules.FromCalendarWeekRule(CalendarWeekRule.FirstDay + 1000, DayOfWeek.Monday)); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Running; 6 | using System.Reflection; 7 | 8 | namespace NodaTime.Benchmarks 9 | { 10 | /// 11 | /// Entry point for benchmarking. 12 | /// 13 | public class Program 14 | { 15 | // Run it with args = { "*" } for choosing all of target benchmarks 16 | public static void Main(string[] args) 17 | { 18 | new BenchmarkSwitcher(typeof(Program).Assembly).Run(args); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Extensions/TimeSpanExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Extensions; 6 | using NUnit.Framework; 7 | using System; 8 | 9 | namespace NodaTime.Test.Extensions 10 | { 11 | public class TimeSpanExtensionsTest 12 | { 13 | [Test] 14 | public void ToDuration() 15 | { 16 | var timeSpan = TimeSpan.FromTicks(123456789012345L); 17 | var duration = timeSpan.ToDuration(); 18 | Assert.AreEqual(123456789012345, duration.BclCompatibleTicks); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NodaTime/Text/Patterns/IPatternParser.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Globalization; 6 | 7 | namespace NodaTime.Text.Patterns 8 | { 9 | /// 10 | /// Internal interface used by FixedFormatInfoPatternParser. Unfortunately 11 | /// even though this is internal, implementations must either use public methods 12 | /// or explicit interface implementation. 13 | /// 14 | internal interface IPatternParser 15 | { 16 | IPattern ParsePattern(string pattern, NodaFormatInfo formatInfo); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/NodaTime.AotCompatibilityTestApp/NodaTime.AotCompatibilityTestApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | true 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /AUTHORS.txt: -------------------------------------------------------------------------------- 1 | Noda Time contains code contributed by: 2 | 3 | Andrey Akinshin 4 | Carlos Schults 5 | David Nelson 6 | Dmitry Bulavin 7 | Dor "The Configurator" Kleiman 8 | James Keesey 9 | Jesse Taber 10 | Jon Skeet 11 | Lasse V. Karlsen 12 | Malcolm Rowe (Google) 13 | Martinho Fernandes 14 | Matt Johnson 15 | Matthew Scharley 16 | Nathan Palmer 17 | Richard Schneider 18 | Scott Stephens 19 | -------------------------------------------------------------------------------- /src/NodaTime.Demo/NodaTime.Demo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | XmlSchemaDemo.cs 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Extensions/DateOnlyExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | #if NET6_0_OR_GREATER 6 | using NodaTime.Extensions; 7 | using NUnit.Framework; 8 | using System; 9 | 10 | namespace NodaTime.Test.Extensions 11 | { 12 | public class DateOnlyExtensionsTest 13 | { 14 | [Test] 15 | public void ToLocalDate() 16 | { 17 | var dateOnly = new DateOnly(2011, 8, 18); 18 | var expected = new LocalDate(2011, 8, 18); 19 | var actual = dateOnly.ToLocalDate(); 20 | Assert.AreEqual(expected, actual); 21 | } 22 | } 23 | } 24 | #endif 25 | -------------------------------------------------------------------------------- /src/NodaTime/Annotations/SpecialNullHandlingAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using System; 5 | 6 | namespace NodaTime.Annotations 7 | { 8 | /// 9 | /// Indicates that the parameter doesn't conform to simple NotNull/CanBeNull 10 | /// behaviour, e.g. for IPattern{T}.Parse, where the parameter shouldn't be null, 11 | /// but the result will be a failed ParseResult rather than an ArgumentNullException. 12 | /// 13 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] 14 | internal sealed class SpecialNullHandlingAttribute : Attribute { } 15 | } 16 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/Calendars/SimpleWeekYearRuleBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using NodaTime.Calendars; 7 | 8 | namespace NodaTime.Benchmarks.NodaTimeTests.Calendars 9 | { 10 | public class SimpleWeekYearRuleBenchmarks 11 | { 12 | private static readonly LocalDate Sample = new LocalDate(2009, 12, 26); 13 | 14 | [Benchmark] 15 | public int IsoWeekOfWeekYear() => WeekYearRules.Iso.GetWeekOfWeekYear(Sample); 16 | 17 | [Benchmark] 18 | public int IsoWeekYear() => WeekYearRules.Iso.GetWeekYear(Sample); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/NodaTime/Fields/DatePeriodFields.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime.Fields 6 | { 7 | /// 8 | /// All the period fields. 9 | /// 10 | internal static class DatePeriodFields 11 | { 12 | internal static IDatePeriodField DaysField { get; } = new FixedLengthDatePeriodField(1); 13 | internal static IDatePeriodField WeeksField { get; } = new FixedLengthDatePeriodField(7); 14 | internal static IDatePeriodField MonthsField { get; } = new MonthsPeriodField(); 15 | internal static IDatePeriodField YearsField { get; } = new YearsPeriodField(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packaging/NodaTime.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | $(MSBuildThisFileDirectory)..\lib\netstandard2.0\NodaTime.dll 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Extensions/TimeOnlyExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | #if NET6_0_OR_GREATER 6 | using NodaTime.Extensions; 7 | using NUnit.Framework; 8 | using System; 9 | 10 | namespace NodaTime.Test.Extensions 11 | { 12 | public class TimeOnlyExtensionsTest 13 | { 14 | [Test] 15 | public void ToLocalTime() 16 | { 17 | var timeOnly = new TimeOnly(12, 34, 56, 300).Add(TimeSpan.FromTicks(4567)); 18 | var expected = new LocalTime(12, 34, 56, 300).PlusTicks(4567); 19 | var actual = timeOnly.ToLocalTime(); 20 | Assert.AreEqual(expected, actual); 21 | } 22 | } 23 | } 24 | #endif 25 | -------------------------------------------------------------------------------- /src/NodaTime/Utility/ReferenceEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.Collections.Generic; 6 | using System.Runtime.CompilerServices; 7 | 8 | namespace NodaTime.Utility 9 | { 10 | /// 11 | /// An equality comparer which compares references for equality and uses the "original" object hash code 12 | /// for hash codes. 13 | /// 14 | internal sealed class ReferenceEqualityComparer : IEqualityComparer where T : class 15 | { 16 | public bool Equals(T? first, T? second) => ReferenceEquals(first, second); 17 | 18 | public int GetHashCode(T value) => value is null ? 0 : RuntimeHelpers.GetHashCode(value); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Extensions/StopwatchExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Extensions; 6 | using NUnit.Framework; 7 | using System.Diagnostics; 8 | using System.Threading; 9 | 10 | namespace NodaTime.Test.Extensions 11 | { 12 | public class StopwatchExtensionsTest 13 | { 14 | [Test] 15 | public void ElapsedDuration() 16 | { 17 | var stopwatch = Stopwatch.StartNew(); 18 | Thread.Sleep(1); 19 | stopwatch.Stop(); 20 | var duration = stopwatch.ElapsedDuration(); 21 | var timespan = stopwatch.Elapsed; 22 | Assert.AreEqual(timespan.Ticks, duration.BclCompatibleTicks); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/CategoryAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime.Benchmarks 8 | { 9 | /// 10 | /// Temporary measure until BenchmarkDotNet supports categories. 11 | /// This allows us to keep our old attributes without losing 12 | /// any information. 13 | /// See https://github.com/PerfDotNet/BenchmarkDotNet/issues/248 14 | /// 15 | [AttributeUsage(AttributeTargets.All)] 16 | internal class CategoryAttribute : Attribute 17 | { 18 | public string Category { get; set; } 19 | 20 | public CategoryAttribute(string category) 21 | { 22 | Category = category; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/NodaTime/Extensions/TimeOnlyExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | #if NET6_0_OR_GREATER 6 | using System; 7 | 8 | namespace NodaTime.Extensions 9 | { 10 | /// 11 | /// Extension methods for . 12 | /// 13 | public static class TimeOnlyExtensions 14 | { 15 | /// 16 | /// Converts a to the equivalent . 17 | /// 18 | /// The time of day to convert. 19 | /// The equivalent. 20 | public static LocalTime ToLocalTime(this TimeOnly time) => LocalTime.FromTimeOnly(time); 21 | } 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /src/NodaTime.TzdbCompiler.Test/Tzdb/RuleLineTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.TimeZones; 6 | using NodaTime.TzdbCompiler.Tzdb; 7 | using NUnit.Framework; 8 | 9 | namespace NodaTime.TzdbCompiler.Test.Tzdb 10 | { 11 | public class RuleLineTest 12 | { 13 | [Test] 14 | public void Equality() 15 | { 16 | var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight); 17 | var recurrence = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009); 18 | var actual = new RuleLine(recurrence, "D"); 19 | var expected = new RuleLine(recurrence, "D"); 20 | Assert.AreEqual(expected, actual); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NodaTime/Extensions/DateOnlyExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | #if NET6_0_OR_GREATER 6 | using System; 7 | 8 | namespace NodaTime.Extensions 9 | { 10 | /// 11 | /// Extension methods for . 12 | /// 13 | public static class DateOnlyExtensions 14 | { 15 | /// 16 | /// Converts a to the equivalent . 17 | /// 18 | /// The date to convert. 19 | /// The equivalent, which is always in the ISO calendar system. 20 | public static LocalDate ToLocalDate(this DateOnly date) => LocalDate.FromDateOnly(date); 21 | } 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /src/NodaTime/TimeZones/TransitionMode.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime.TimeZones 6 | { 7 | /// 8 | /// Specifies how transitions are calculated. Whether relative to UTC, the time zones standard 9 | /// offset, or the wall (or daylight savings) offset. 10 | /// 11 | internal enum TransitionMode 12 | { 13 | /// 14 | /// Calculate transitions against UTC. 15 | /// 16 | Utc = 0, 17 | 18 | /// 19 | /// Calculate transitions against wall offset. 20 | /// 21 | Wall = 1, 22 | 23 | /// 24 | /// Calculate transitions against standard offset. 25 | /// 26 | Standard = 2 27 | } 28 | } -------------------------------------------------------------------------------- /src/NodaTime.Test/TimeZones/TzTestHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.TimeZones; 6 | 7 | namespace NodaTime.Test.TimeZones 8 | { 9 | /// 10 | /// Extension methods to help with time zone testing, and other helper methods. 11 | /// 12 | internal static class TzTestHelper 13 | { 14 | /// 15 | /// Returns the uncached version of the given zone. If the zone isn't 16 | /// an instance of CachedDateTimeZone, the same reference is returned back. 17 | /// 18 | internal static DateTimeZone Uncached(this DateTimeZone zone) 19 | { 20 | var cached = zone as CachedDateTimeZone; 21 | return cached is null ? zone : cached.TimeZone; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/NodaTime.Tools.Common/FileUtility.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.IO; 6 | using System.Net.Http; 7 | using System.Threading.Tasks; 8 | 9 | namespace NodaTime.Tools.Common 10 | { 11 | public static class FileUtility 12 | { 13 | public static async Task LoadFileOrUrlAsync(string source) 14 | { 15 | if (source.StartsWith("http://") || source.StartsWith("https://") || source.StartsWith("ftp://")) 16 | { 17 | using var client = new HttpClient(); 18 | var response = await client.GetAsync(source); 19 | return await response.EnsureSuccessStatusCode().Content.ReadAsByteArrayAsync(); 20 | } 21 | return File.ReadAllBytes(source); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/NodaTime/TimeZones/IZoneIntervalMap.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime.TimeZones 6 | { 7 | /// 8 | /// The core part of a DateTimeZone: mapping an Instant to an Interval. 9 | /// Separating this out into an interface allows for flexible caching. 10 | /// 11 | /// 12 | /// Benchmarking shows that a delegate may be slightly faster here, but the difference 13 | /// isn't very significant even for very fast calls (cache hits). The interface ends up 14 | /// feeling slightly cleaner elsewhere in the code. 15 | /// 16 | internal interface IZoneIntervalMap 17 | { 18 | ZoneInterval GetZoneInterval(Instant instant); 19 | Offset MinOffset { get; } 20 | Offset MaxOffset { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/NodaTime/TimeZones/SingleZoneIntervalMap.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime.TimeZones 6 | { 7 | /// 8 | /// Implementation of IZoneIntervalMap which just returns a single interval (provided on construction) regardless of 9 | /// the instant requested. 10 | /// 11 | internal sealed class SingleZoneIntervalMap : IZoneIntervalMap 12 | { 13 | private readonly ZoneInterval interval; 14 | 15 | public Offset MinOffset => interval.WallOffset; 16 | public Offset MaxOffset => interval.WallOffset; 17 | 18 | internal SingleZoneIntervalMap(ZoneInterval interval) 19 | { 20 | this.interval = interval; 21 | } 22 | 23 | public ZoneInterval GetZoneInterval(Instant instant) => interval; 24 | } 25 | } -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/ZoneYearOffsetBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using NodaTime.TimeZones; 7 | 8 | namespace NodaTime.Benchmarks.NodaTimeTests 9 | { 10 | public class ZoneYearOffsetBenchmarks 11 | { 12 | private static readonly ZoneYearOffset Sample = 13 | new ZoneYearOffset(TransitionMode.Wall, 3, 15, (int)IsoDayOfWeek.Sunday, true, new LocalTime(1, 0, 0)); 14 | 15 | [Benchmark] 16 | public LocalInstantWrapper GetOccurrenceForYear() => new LocalInstantWrapper(Sample.GetOccurrenceForYear(2010)); 17 | 18 | public struct LocalInstantWrapper 19 | { 20 | private readonly LocalInstant value; 21 | internal LocalInstantWrapper(LocalInstant value) => this.value = value; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/NodaTime/Annotations/TestExemptionAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using System; 5 | 6 | namespace NodaTime.Annotations 7 | { 8 | /// 9 | /// Attribute to effectively ignore a particular kind of test, because it's known 10 | /// not to apply to this member. The optional message isn't stored, because we never 11 | /// need it - it's for documentation purposes. 12 | /// 13 | [AttributeUsage(AttributeTargets.All)] 14 | internal sealed class TestExemptionAttribute : Attribute 15 | { 16 | internal TestExemptionCategory Category { get; } 17 | 18 | internal TestExemptionAttribute(TestExemptionCategory category) 19 | { 20 | Category = category; 21 | } 22 | } 23 | 24 | internal enum TestExemptionCategory 25 | { 26 | ConversionName = 1 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Extensions/DateTimeZoneProviderExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Extensions; 6 | using NodaTime.Testing.TimeZones; 7 | using NUnit.Framework; 8 | 9 | namespace NodaTime.Test.Extensions 10 | { 11 | public class DayOfWeekExtensionsTest 12 | { 13 | [Test] 14 | public void GetAllZones() 15 | { 16 | // Note: in ID order. 17 | var zone1 = DateTimeZoneProviders.Tzdb["America/New_York"]; 18 | var zone2 = DateTimeZoneProviders.Tzdb["Europe/London"]; 19 | var zone3 = DateTimeZoneProviders.Tzdb["Europe/Paris"]; 20 | 21 | var provider = new FakeDateTimeZoneSource.Builder { zone1, zone2, zone3 }.Build().ToProvider(); 22 | CollectionAssert.AreEqual(new[] { zone1, zone2, zone3 }, provider.GetAllZones()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/NodaTime.Test/TimeZones/IO/TzdbStreamFieldTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.TimeZones.IO; 6 | using NodaTime.Utility; 7 | using NUnit.Framework; 8 | using System.IO; 9 | 10 | namespace NodaTime.Test.TimeZones.IO 11 | { 12 | public class TzdbStreamFieldTest 13 | { 14 | // Only tests for situations which aren't covered elsewhere 15 | 16 | [Test] 17 | public void InsufficientData() 18 | { 19 | var stream = new MemoryStream(); 20 | var writer = new DateTimeZoneWriter(stream, null); 21 | writer.WriteByte(1); 22 | writer.WriteCount(10); 23 | 24 | stream.Position = 0; 25 | var iterator = TzdbStreamField.ReadFields(stream).GetEnumerator(); 26 | 27 | Assert.Throws(() => iterator.MoveNext()); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/NodaTime/Annotations/VisibleForTestingAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime.Annotations 8 | { 9 | /// 10 | /// Attribute indicating that a particular member would normally be private (or potentially protected) 11 | /// but is exposed for test purposes. 12 | /// 13 | /// 14 | /// Currently this excludes field and events - but it could be expanded to do so. Likewise 15 | /// we don't indicate the intended access mode, which could be done via an enum. For the moment we'll 16 | /// assume everything would be private apart from for testing. 17 | /// 18 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property)] 19 | internal class VisibleForTestingAttribute : Attribute 20 | { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Text/PatternNamingTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | using System.Linq; 7 | using System.Reflection; 8 | 9 | namespace NodaTime.Test.Text 10 | { 11 | public class PatternNamingTest 12 | { 13 | // https://github.com/nodatime/nodatime/issues/556 14 | [Test] 15 | public void NoPatternSuffix() 16 | { 17 | var properties = 18 | from type in typeof(Instant).Assembly.DefinedTypes 19 | where type.Name.EndsWith("Pattern") 20 | from property in type.DeclaredProperties 21 | where property.GetMethod?.IsStatic == true && property.Name.EndsWith("Pattern") 22 | select $"{type.Name}.{property.Name}"; 23 | Assert.IsEmpty(properties, $"Badly named properties: {string.Join(", ", properties)}"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/NodaTime/Extensions/IsoDayOfWeekExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Utility; 6 | using System; 7 | 8 | namespace NodaTime.Extensions 9 | { 10 | /// 11 | /// Extension methods 12 | /// 13 | public static class IsoDayOfWeekExtensions 14 | { 15 | /// 16 | /// Converts a into the corresponding . 17 | /// 18 | /// This is a convenience method which calls . 19 | /// The IsoDayOfWeek to convert. 20 | /// The DayOfWeek equivalent to 21 | public static DayOfWeek ToDayOfWeek(this IsoDayOfWeek isoDayOfWeek) => BclConversions.ToDayOfWeek(isoDayOfWeek); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NodaTime/Text/ParseBucket.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Text.Patterns; 6 | 7 | namespace NodaTime.Text 8 | { 9 | /// 10 | /// Base class for "buckets" of parse data - as field values are parsed, they are stored in a bucket, 11 | /// then the final value is calculated at the end. 12 | /// 13 | internal abstract class ParseBucket 14 | { 15 | /// 16 | /// Performs the final conversion from fields to a value. The parse can still fail here, if there 17 | /// are incompatible field values. 18 | /// 19 | /// Indicates which fields were part of the original text pattern. 20 | /// Complete value being parsed 21 | internal abstract ParseResult CalculateValue(PatternFields usedFields, string value); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NodaTime/Text/IPartialPattern.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime.Text 6 | { 7 | /// 8 | /// Internal interface supporting partial parsing and formatting. This is used 9 | /// when one pattern is embedded within another. 10 | /// 11 | /// The type of value to be parsed or formatted. 12 | internal interface IPartialPattern : IPattern 13 | { 14 | /// 15 | /// Parses a value from the current position in the cursor. This will 16 | /// not fail if the pattern ends before the cursor does - that's expected 17 | /// in most cases. 18 | /// 19 | /// The cursor to parse from. 20 | /// The result of parsing from the cursor. 21 | ParseResult ParsePartial(ValueCursor cursor); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NodaTime/Extensions/DayOfWeekExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Utility; 6 | using System; 7 | 8 | namespace NodaTime.Extensions 9 | { 10 | /// 11 | /// Extension methods for . 12 | /// 13 | public static class DayOfWeekExtensions 14 | { 15 | /// 16 | /// Converts a into the corresponding . 17 | /// 18 | /// This is a convenience method which calls . 19 | /// The DayOfWeek to convert. 20 | /// The IsoDayOfWeek equivalent to 21 | public static IsoDayOfWeek ToIsoDayOfWeek(this DayOfWeek dayOfWeek) => BclConversions.ToIsoDayOfWeek(dayOfWeek); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NodaTime.Test/TimeZones/TzdbDateTimeZoneTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Extensions; 6 | using NUnit.Framework; 7 | using System.Collections.Generic; 8 | 9 | namespace NodaTime.Test.TimeZones 10 | { 11 | /// 12 | /// Tests for all TZDB time zones. 13 | /// 14 | public class TzdbDateTimeZoneTest 15 | { 16 | private static readonly IEnumerable AllTzdbZones = DateTimeZoneProviders.Tzdb.GetAllZones(); 17 | 18 | [Test] 19 | [TestCaseSource(nameof(AllTzdbZones))] 20 | public void AllZonesStartAndEndOfTime(DateTimeZone zone) 21 | { 22 | var firstInterval = zone.GetZoneInterval(Instant.MinValue); 23 | Assert.IsFalse(firstInterval.HasStart); 24 | var lastInterval = zone.GetZoneInterval(Instant.MaxValue); 25 | Assert.IsFalse(lastInterval.HasEnd); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/NodaTime/Extensions/StopwatchExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using NodaTime.Utility; 5 | using System.Diagnostics; 6 | 7 | namespace NodaTime.Extensions 8 | { 9 | /// 10 | /// Extension methods for . 11 | /// 12 | public static class StopwatchExtensions 13 | { 14 | /// 15 | /// Returns the elapsed time of as a . 16 | /// 17 | /// The Stopwatch to obtain the elapsed time from. 18 | /// The elapsed time of as a Duration. 19 | public static Duration ElapsedDuration(this Stopwatch stopwatch) 20 | { 21 | Preconditions.CheckNotNull(stopwatch, nameof(stopwatch)); 22 | return stopwatch.Elapsed.ToDuration(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/BclDateTimeZoneBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using BenchmarkDotNet.Attributes; 5 | using NodaTime.Benchmarks.BclTests; 6 | using NodaTime.TimeZones; 7 | 8 | namespace NodaTime.Benchmarks.NodaTimeTests 9 | { 10 | public class BclDateTimeZoneBenchmarks 11 | { 12 | private static readonly DateTimeZone PacificZone = BclDateTimeZone.FromTimeZoneInfo(TimeZoneInfoBenchmarks.PacificZone); 13 | private static readonly Instant SummerInstant = Instant.FromDateTimeUtc(TimeZoneInfoBenchmarks.SummerUtc); 14 | private static readonly Instant WinterInstant = Instant.FromDateTimeUtc(TimeZoneInfoBenchmarks.WinterUtc); 15 | 16 | // This is somewhat unfair due to caching, admittedly... 17 | [Benchmark] 18 | public void GetZoneInterval() 19 | { 20 | PacificZone.GetZoneInterval(SummerInstant); 21 | PacificZone.GetZoneInterval(WinterInstant); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Ignore.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | using System; 7 | 8 | namespace NodaTime.Test 9 | { 10 | /// 11 | /// Convenience class for ignoring tests based on conditions at execution time. 12 | /// 13 | public static class Ignore 14 | { 15 | public static void When(bool condition, string message) 16 | { 17 | if (condition) 18 | { 19 | Assert.Ignore(message); 20 | } 21 | } 22 | 23 | /// 24 | /// Calls Assert.Ignore, which always throws an exception - but with a return type 25 | /// of T, which makes it easier to call in expression-bodied members. 26 | /// 27 | public static T Throw(string message) 28 | { 29 | Assert.Ignore(message); 30 | throw new InvalidOperationException($"Expected Assert.Ignore to throw"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Push packages to NuGet 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | 9 | release: 10 | runs-on: ubuntu-latest 11 | env: 12 | DOTNET_NOLOGO: true 13 | 14 | steps: 15 | - name: Check out our repo 16 | uses: actions/checkout@v3 17 | with: 18 | submodules: true 19 | 20 | - name: Setup .NET 21 | uses: actions/setup-dotnet@v3 22 | with: 23 | dotnet-version: | 24 | 6.0.x 25 | 8.0.x 26 | 27 | - name: Build and test 28 | run: | 29 | build/ci.sh 30 | dotnet test -c Release -f net8.0 --filter TestCategory=Slow src/NodaTime.Test 31 | mkdir nuget 32 | dotnet pack -c Release -o ./nuget src/NodaTime 33 | dotnet pack -c Release -o ./nuget src/NodaTime.Test 34 | 35 | - name: Push to NuGet 36 | run: | 37 | echo "Pushing to NuGet from GitHub disabled until we've got signing sorted" 38 | exit 1 39 | # for file in nuget/*.nupkg; do dotnet nuget push -s https://api.nuget.org/v3/index.json -k ${{secrets.NUGET_API_KEY}} $file; done 40 | -------------------------------------------------------------------------------- /src/NodaTime.Test/NamedWrapper.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime.Test 6 | { 7 | /// 8 | /// Test parameters are converted into strings to generate 9 | /// test names; this can cause problems either due to non-uniqueness, 10 | /// or due to brackets in the name. This wrapper allows custom names to 11 | /// be provided, and automatically converts round brackets to square ones. 12 | /// 13 | /// Type of underlying value 14 | public class NamedWrapper 15 | { 16 | public T Value { get; } 17 | private readonly string name; 18 | 19 | public NamedWrapper(T value, string name) 20 | { 21 | Value = value; 22 | this.name = name; 23 | } 24 | 25 | public override string ToString() => SanitizeName(name); 26 | 27 | internal static string SanitizeName(string name) => name.Replace('(', '[').Replace(')', ']'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/NodaTime/Fields/MonthsPeriodField.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Calendars; 6 | 7 | namespace NodaTime.Fields 8 | { 9 | /// 10 | /// Period field which uses a to add/subtract months. 11 | /// 12 | internal sealed class MonthsPeriodField : IDatePeriodField 13 | { 14 | internal MonthsPeriodField() 15 | { 16 | } 17 | 18 | public LocalDate Add(LocalDate localDate, int value) 19 | { 20 | var calendar = localDate.Calendar; 21 | var calculator = calendar.YearMonthDayCalculator; 22 | var yearMonthDay = calculator.AddMonths(localDate.YearMonthDay, value); 23 | return new LocalDate(yearMonthDay.WithCalendar(calendar)); 24 | } 25 | 26 | public int UnitsBetween(LocalDate start, LocalDate end) => 27 | start.Calendar.YearMonthDayCalculator.MonthsBetween(start.YearMonthDay, end.YearMonthDay); 28 | } 29 | } -------------------------------------------------------------------------------- /src/NodaTime.Testing/Preconditions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime.Testing 8 | { 9 | /// 10 | /// Helper static methods for argument/state validation. Copied from NodaTime.Utility, 11 | /// as we don't want the Testing assembly to have internal access to NodaTime, but we 12 | /// don't really want to expose Preconditions publicly. 13 | /// 14 | internal static class Preconditions 15 | { 16 | /// 17 | /// Returns the given argument after checking whether it's null. This is useful for putting 18 | /// nullity checks in parameters which are passed to base class constructors. 19 | /// 20 | internal static T CheckNotNull(T argument, string paramName) where T : class 21 | { 22 | if (argument is null) 23 | { 24 | throw new ArgumentNullException(paramName); 25 | } 26 | return argument; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/NodaTime/Annotations/TrustedAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Utility; 6 | using System; 7 | 8 | namespace NodaTime.Annotations 9 | { 10 | /// 11 | /// Indicates that a parameter is trusted to be valid, so callers must take care 12 | /// to only pass valid values. 13 | /// 14 | /// 15 | /// This attribute should never be applied to parameters in public members, as 16 | /// all public members should validate their parameters. The exception here is 17 | /// public members within internal types, as those aren't really exposed publicly. 18 | /// Parameters decorated with this attribute should typically be validated in 19 | /// debug configurations, using 20 | /// or a similar method. 21 | /// 22 | [AttributeUsage(AttributeTargets.Parameter)] 23 | internal sealed class TrustedAttribute : Attribute 24 | { 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/NodaTime/Extensions/DateTimeZoneProviderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using NodaTime.Utility; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace NodaTime.Extensions 9 | { 10 | /// 11 | /// Extensions for 12 | /// 13 | public static class DateTimeZoneProviderExtensions 14 | { 15 | /// 16 | /// Returns a lazily-evaluated sequence of time zones from the specified provider, 17 | /// in the same order in which the IDs are returned by the provider. 18 | /// 19 | /// The provider to fetch time zones from. 20 | /// All the time zones from the provider. 21 | public static IEnumerable GetAllZones(this IDateTimeZoneProvider provider) 22 | { 23 | Preconditions.CheckNotNull(provider, nameof(provider)); 24 | return provider.Ids.Select(id => provider[id]); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Text/PeriodPatternTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Text; 6 | 7 | namespace NodaTime.Test.Text 8 | { 9 | // Container class just to house the nested types 10 | public static partial class PeriodPatternTest 11 | { 12 | /// 13 | /// A container for test data for formatting and parsing objects. 14 | /// 15 | public sealed class Data : PatternTestData 16 | { 17 | // Irrelevant 18 | protected override Period DefaultTemplate => Period.FromDays(0); 19 | 20 | public Data() : this(Period.FromDays(0)) 21 | { 22 | } 23 | 24 | public Data(Period value) : base(value) 25 | { 26 | this.StandardPattern = PeriodPattern.Roundtrip; 27 | } 28 | 29 | public Data(PeriodBuilder builder) : this(builder.Build()) 30 | { 31 | } 32 | 33 | internal override IPattern CreatePattern() => StandardPattern!; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/NodaTime/Text/FixedFormatInfoPatternParser.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Globalization; 6 | using NodaTime.Text.Patterns; 7 | using NodaTime.Utility; 8 | using System; 9 | 10 | namespace NodaTime.Text 11 | { 12 | /// 13 | /// A pattern parser for a single format info, which caches patterns by text/style. 14 | /// 15 | internal sealed class FixedFormatInfoPatternParser 16 | { 17 | // It would be unusual to have more than 50 different patterns for a specific culture 18 | // within a real app. 19 | private const int CacheSize = 50; 20 | private readonly Cache> cache; 21 | 22 | internal FixedFormatInfoPatternParser(IPatternParser patternParser, NodaFormatInfo formatInfo) 23 | { 24 | cache = new Cache>(CacheSize, patternText => patternParser.ParsePattern(patternText, formatInfo), 25 | StringComparer.Ordinal); 26 | } 27 | 28 | internal IPattern ParsePattern(string pattern) => cache.GetOrAdd(pattern); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![GitHub Actions status](https://img.shields.io/github/actions/workflow/status/nodatime/nodatime/push.yaml?branch=main)](https://github.com/nodatime/nodatime/actions/workflows/push.yaml) 2 | [![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/kw664whqre92a00m?svg=true)](https://ci.appveyor.com/project/nodatime/nodatime) 3 | [![Coverage Status](https://codecov.io/gh/nodatime/nodatime/branch/main/graph/badge.svg)](https://codecov.io/gh/nodatime/nodatime) 4 | 5 | Noda Time is an alternative date and time API for .NET. It helps you to 6 | think about your data more clearly, and express operations on that data more 7 | precisely. 8 | 9 | * [Project web site](https://nodatime.org) - for documentation, installation, downloads etc 10 | * [Group/mailing list](https://groups.google.com/group/noda-time) - for discussion of potential features 11 | * [Project source and issue site](https://github.com/nodatime/nodatime) 12 | * [Stack Overflow tag](http://stackoverflow.com/questions/tagged/nodatime) - for specific "How do I do X?" questions 13 | 14 | ## Contributing 15 | 16 | We appreciate your interest in contributing to Noda Time. See the [contribution guidelines](https://github.com/nodatime/nodatime/blob/main/CONTRIBUTING.md) for more details. 17 | -------------------------------------------------------------------------------- /lib/commandline/LICENSE: -------------------------------------------------------------------------------- 1 | Command Line Parser Library 2 | 3 | Author: 4 | Giacomo Stelluti Scala (gsscoder@ymail.com) 5 | 6 | Copyright (c) 2005 - 2009 Giacomo Stelluti Scala 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /src/NodaTime/Calendars/IslamicEpoch.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | 6 | namespace NodaTime.Calendars 7 | { 8 | /// 9 | /// The epoch to use when constructing an Islamic calendar. 10 | /// 11 | /// 12 | /// The Islamic, or Hijri, calendar can either be constructed 13 | /// starting on July 15th 622CE (in the Julian calendar) or on the following day. 14 | /// The former is the "astronomical" or "Thursday" epoch; the latter is the "civil" or "Friday" epoch. 15 | /// 16 | /// 17 | public enum IslamicEpoch 18 | { 19 | /// 20 | /// Epoch beginning on July 15th 622CE (Julian), which is July 18th 622 CE in the Gregorian calendar. 21 | /// This is the epoch used by the BCL HijriCalendar. 22 | /// 23 | Astronomical = 1, 24 | 25 | /// 26 | /// Epoch beginning on July 16th 622CE (Julian), which is July 19th 622 CE in the Gregorian calendar. 27 | /// 28 | Civil = 2 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks.Custom/ConcurrentNoOp.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.Threading; 6 | 7 | namespace NodaTime.Benchmarks.Custom; 8 | 9 | internal class ConcurrentNoOp : ConcurrencyCommandBase 10 | { 11 | private ConcurrentNoOp(int threadCount, Duration executionTime) : base(threadCount, executionTime) 12 | { 13 | } 14 | 15 | protected override void DoWork() 16 | { 17 | while (Interlocked.Add(ref iterations, ChunkSize) > 0) 18 | { 19 | for (int i = 0; i < ChunkSize; i++) 20 | { 21 | } 22 | } 23 | } 24 | 25 | internal static void Execute(string[] args) 26 | { 27 | if (args.Length != 2) 28 | { 29 | throw new ConfigurationException("Command arguments: "); 30 | } 31 | 32 | int threadCount = int.Parse(args[0]); 33 | int executionTimeSeconds = int.Parse(args[1]); 34 | var command = new ConcurrentNoOp(threadCount, Duration.FromSeconds(executionTimeSeconds)); 35 | command.Execute(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/NodaTime.Test/TimeAdjustersTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using NUnit.Framework; 5 | 6 | namespace NodaTime.Test 7 | { 8 | public class TimeAdjustersTest 9 | { 10 | [Test] 11 | public void TruncateToSecond() 12 | { 13 | var start = LocalTime.FromHourMinuteSecondMillisecondTick(7, 4, 30, 123, 4567); 14 | var end = new LocalTime(7, 4, 30); 15 | Assert.AreEqual(end, TimeAdjusters.TruncateToSecond(start)); 16 | } 17 | 18 | [Test] 19 | public void TruncateToMinute() 20 | { 21 | var start = LocalTime.FromHourMinuteSecondMillisecondTick(7, 4, 30, 123, 4567); 22 | var end = new LocalTime(7, 4, 0); 23 | Assert.AreEqual(end, TimeAdjusters.TruncateToMinute(start)); 24 | } 25 | 26 | [Test] 27 | public void TruncateToHour() 28 | { 29 | var start = LocalTime.FromHourMinuteSecondMillisecondTick(7, 4, 30, 123, 4567); 30 | var end = new LocalTime(7, 0, 0); 31 | Assert.AreEqual(end, TimeAdjusters.TruncateToHour(start)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/NodaTime.Demo/PeriodBuilderDemo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | 7 | namespace NodaTime.Demo 8 | { 9 | public class PeriodBuilderDemo 10 | { 11 | [Test] 12 | public void ConstructionFromPeriod() 13 | { 14 | Period existingPeriod = Period.FromYears(5); 15 | PeriodBuilder periodBuilder = Snippet.For(new PeriodBuilder(existingPeriod)); 16 | periodBuilder.Months = 6; 17 | Period period = periodBuilder.Build(); 18 | Assert.AreEqual(5, period.Years); 19 | Assert.AreEqual(6, period.Months); 20 | } 21 | 22 | [Test] 23 | public void Build() 24 | { 25 | PeriodBuilder periodBuilder = new PeriodBuilder() 26 | { 27 | Years = 2, 28 | Months = 3, 29 | Days = 4 30 | }; 31 | Period period = Snippet.For(periodBuilder.Build()); 32 | Assert.AreEqual(2, period.Years); 33 | Assert.AreEqual(3, period.Months); 34 | Assert.AreEqual(4, period.Days); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/Text/ZonedDateTimePatternBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using NodaTime.Text; 7 | 8 | #if !V1_0 && !V1_1 9 | namespace NodaTime.Benchmarks.NodaTimeTests.Text 10 | { 11 | [Category("Text")] 12 | public class ZonedDateTimePatternBenchmarks 13 | { 14 | private static readonly DateTimeZone SampleZone = DateTimeZoneProviders.Tzdb["America/Los_Angeles"]; 15 | private static readonly ZonedDateTime SampleZonedDateTime = new LocalDateTime(2009, 12, 26, 10, 8, 30).InZoneStrictly(SampleZone); 16 | private static readonly ZonedDateTimePattern PatternWithNumbersToSecond = ZonedDateTimePattern.CreateWithInvariantCulture("dd/MM/uuuu HH:mm:ss", null); 17 | 18 | [Benchmark] 19 | public void FormatWithNumbersToSecond() 20 | { 21 | PatternWithNumbersToSecond.Format(SampleZonedDateTime); 22 | } 23 | 24 | [Benchmark] 25 | public void FormatIso() 26 | { 27 | ZonedDateTimePattern.ExtendedFormatOnlyIso.Format(SampleZonedDateTime); 28 | } 29 | } 30 | } 31 | #endif 32 | -------------------------------------------------------------------------------- /src/NodaTime.Testing/NodaTime.Testing.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Provides extra types which may be useful when testing code which uses Noda Time, such as a fake programmable implementation of IClock and a time zone which has a fixed transition. These types are also used to test Noda Time itself. 5 | netstandard2.0 6 | true 7 | True 8 | true 9 | true 10 | nodatime;testing 11 | README.md 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | all 22 | runtime; build; native; contentfiles; analyzers 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/NodaTime/Calendars/EraCalculator.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | 8 | namespace NodaTime.Calendars 9 | { 10 | /// 11 | /// Takes responsibility for all era-based calculations for a calendar. 12 | /// YearMonthDay arguments can be assumed to be valid for the relevant calendar, 13 | /// but other arguments should be validated. (Eras should be validated for nullity as well 14 | /// as for the presence of a particular era.) 15 | /// 16 | internal abstract class EraCalculator 17 | { 18 | internal ReadOnlyCollection Eras { get; } 19 | 20 | protected EraCalculator(params Era[] eras) 21 | { 22 | this.Eras = new ReadOnlyCollection(eras); 23 | } 24 | 25 | internal abstract int GetMinYearOfEra(Era era); 26 | internal abstract int GetMaxYearOfEra(Era era); 27 | internal abstract Era GetEra(int absoluteYear); 28 | internal abstract int GetYearOfEra(int absoluteYear); 29 | internal abstract int GetAbsoluteYear(int yearOfEra, Era era); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/NodaTime.Demo/TimeAdjustersDemo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | 7 | namespace NodaTime.Demo 8 | { 9 | public class TimeAdjustersDemo 10 | { 11 | [Test] 12 | public void TruncateToHour() 13 | { 14 | var time = LocalTime.FromMinutesSinceMidnight(63); 15 | var truncated = Snippet.For(TimeAdjusters.TruncateToHour(time)); 16 | Assert.AreEqual(LocalTime.FromHoursSinceMidnight(1), truncated); 17 | } 18 | 19 | [Test] 20 | public void TruncateToMinute() 21 | { 22 | var time = LocalTime.FromSecondsSinceMidnight(127); 23 | var truncated = Snippet.For(TimeAdjusters.TruncateToMinute(time)); 24 | Assert.AreEqual(LocalTime.FromMinutesSinceMidnight(2), truncated); 25 | } 26 | 27 | [Test] 28 | public void TruncateToSecond() 29 | { 30 | var time = LocalTime.FromMillisecondsSinceMidnight(3042); 31 | var truncated = Snippet.For(TimeAdjusters.TruncateToSecond(time)); 32 | Assert.AreEqual(LocalTime.FromSecondsSinceMidnight(3), truncated); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks.Custom/ConcurrentNewString.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.Threading; 6 | 7 | namespace NodaTime.Benchmarks.Custom; 8 | 9 | internal class ConcurrentNewString : ConcurrencyCommandBase 10 | { 11 | private ConcurrentNewString(int threadCount, Duration executionTime) : base(threadCount, executionTime) 12 | { 13 | } 14 | 15 | protected override void DoWork() 16 | { 17 | while (Interlocked.Add(ref iterations, ChunkSize) > 0) 18 | { 19 | for (int i = 0; i < ChunkSize; i++) 20 | { 21 | _ = new string('x', 8); 22 | } 23 | } 24 | } 25 | 26 | internal static void Execute(string[] args) 27 | { 28 | if (args.Length != 2) 29 | { 30 | throw new ConfigurationException("Command arguments: "); 31 | } 32 | 33 | int threadCount = int.Parse(args[0]); 34 | int executionTimeSeconds = int.Parse(args[1]); 35 | var command = new ConcurrentNewString(threadCount, Duration.FromSeconds(executionTimeSeconds)); 36 | command.Execute(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NodaTime.Demo/LocalDateTimeDemo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.Globalization; 6 | using NUnit.Framework; 7 | using NodaTime.Text; 8 | 9 | namespace NodaTime.Demo 10 | { 11 | public class LocalDateTimeDemo 12 | { 13 | [Test] 14 | public void SimpleConstruction() 15 | { 16 | CalendarSystem calendar = CalendarSystem.Iso; 17 | LocalDateTime dt = Snippet.For(new LocalDateTime(2010, 6, 16, 16, 20, calendar)); 18 | Assert.AreEqual(20, dt.Minute); 19 | } 20 | 21 | [Test] 22 | public void ImplicitIsoCalendar() 23 | { 24 | LocalDateTime dt = Snippet.For(new LocalDateTime(2010, 6, 16, 16, 20)); 25 | Assert.AreEqual("2010-06-16T16:20:00", LocalDateTimePattern.GeneralIso.Format(dt)); 26 | Assert.AreEqual(CalendarSystem.Iso, dt.Calendar); 27 | } 28 | 29 | [Test] 30 | public void TestToString() 31 | { 32 | LocalDateTime dt = new LocalDateTime(2010, 6, 16, 16, 20); 33 | Assert.AreEqual("2010-06-16T16:20:00", Snippet.For(dt.ToString("uuuu-MM-dd'T'HH:mm:ss", CultureInfo.InvariantCulture))); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/NodaTime.Test/Annotations/MutabilityTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using System.Linq; 7 | using System.Reflection; 8 | using NodaTime.Annotations; 9 | using NUnit.Framework; 10 | 11 | namespace NodaTime.Test.Annotations 12 | { 13 | public class MutabilityTest 14 | { 15 | [Test] 16 | public void AllPublicClassesAreMutableOrImmutable() 17 | { 18 | var unannotatedClasses = typeof(Instant).Assembly 19 | .DefinedTypes 20 | .Where(t => t.IsClass && (t.IsNestedPublic || t.IsPublic) && t.BaseType != typeof(MulticastDelegate)) 21 | .Where(t => !(t.IsAbstract && t.IsSealed)) // Ignore static classes 22 | .OrderBy(t => t.Name) 23 | .Where(t => !t.IsDefined(typeof(ImmutableAttribute)) && 24 | !t.IsDefined(typeof(MutableAttribute))); 25 | 26 | TestHelper.AssertNoFailures(unannotatedClasses, c => c.Name); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/NodaTime.Test/NodaConstantsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | using System; 7 | 8 | namespace NodaTime.Test 9 | { 10 | public class NodaConstantsTest 11 | { 12 | [Test] 13 | public void JulianEpoch() 14 | { 15 | // Compute the Julian epoch using the Julian calendar, instead of the 16 | // Gregorian version. 17 | var localEpoch = new LocalDateTime(-4712, 1, 1, 12, 0, CalendarSystem.Julian); 18 | var epoch = localEpoch.InZoneStrictly(DateTimeZone.Utc).ToInstant(); 19 | Assert.AreEqual(epoch, NodaConstants.JulianEpoch); 20 | } 21 | 22 | [Test] 23 | public void BclTicksAtEpoch() 24 | { 25 | Assert.AreEqual( 26 | new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks, 27 | NodaConstants.BclTicksAtUnixEpoch); 28 | } 29 | 30 | [Test] 31 | public void BclDaysAtEpoch() 32 | { 33 | Assert.AreEqual( 34 | new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks, 35 | NodaConstants.TicksPerDay * NodaConstants.BclDaysAtUnixEpoch); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NodaTime/CalendarOrdinal.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime 6 | { 7 | /// 8 | /// Enumeration of calendar ordinal values. Used for converting between a compact integer representation and a calendar system. 9 | /// We use 6 bits to store the calendar ordinal in YearMonthDayCalendar, so we can have up to 64 calendars. 10 | /// 11 | internal enum CalendarOrdinal 12 | { 13 | Iso = 0, 14 | Gregorian = 1, 15 | Julian = 2, 16 | Coptic = 3, 17 | HebrewCivil = 4, 18 | HebrewScriptural = 5, 19 | PersianSimple = 6, 20 | PersianArithmetic = 7, 21 | PersianAstronomical = 8, 22 | IslamicAstronomicalBase15 = 9, 23 | IslamicAstronomicalBase16 = 10, 24 | IslamicAstronomicalIndian = 11, 25 | IslamicAstronomicalHabashAlHasib = 12, 26 | IslamicCivilBase15 = 13, 27 | IslamicCivilBase16 = 14, 28 | IslamicCivilIndian = 15, 29 | IslamicCivilHabashAlHasib = 16, 30 | UmAlQura = 17, 31 | Badi = 18, 32 | // Not a real ordinal; just present to keep a count. Increase this as the number increases... 33 | Size = 19 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks.Custom/ConcurrentToString.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.Threading; 6 | 7 | namespace NodaTime.Benchmarks.Custom; 8 | 9 | internal class ConcurrentToString : ConcurrencyCommandBase 10 | { 11 | private ConcurrentToString(int threadCount, Duration executionTime) : base(threadCount, executionTime) 12 | { 13 | } 14 | 15 | protected override void DoWork() 16 | { 17 | LocalTime localTime = new LocalTime(23, 15, 20); 18 | while (Interlocked.Add(ref iterations, ChunkSize) > 0) 19 | { 20 | for (int i = 0; i < ChunkSize; i++) 21 | { 22 | localTime.ToString(); 23 | } 24 | } 25 | } 26 | 27 | internal static void Execute(string[] args) 28 | { 29 | if (args.Length != 2) 30 | { 31 | throw new ConfigurationException("Command arguments: "); 32 | } 33 | 34 | int threadCount = int.Parse(args[0]); 35 | int executionTimeSeconds = int.Parse(args[1]); 36 | var command = new ConcurrentToString(threadCount, Duration.FromSeconds(executionTimeSeconds)); 37 | command.Execute(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/NodaTime.Test/SystemClockTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using NUnit.Framework; 7 | 8 | namespace NodaTime.Test 9 | { 10 | public class SystemClockTest 11 | { 12 | [Test] 13 | public void InstanceNow() 14 | { 15 | long frameworkNowTicks = NodaConstants.BclEpoch.PlusTicks(DateTime.UtcNow.Ticks).ToUnixTimeTicks(); 16 | long nodaTicks = SystemClock.Instance.GetCurrentInstant().ToUnixTimeTicks(); 17 | Assert.Less(Math.Abs(nodaTicks - frameworkNowTicks), Duration.FromSeconds(1).BclCompatibleTicks); 18 | } 19 | 20 | [Test] 21 | public void Sanity() 22 | { 23 | // Previously all the conversions missed the SystemConversions.DateTimeEpochTicks, 24 | // so they were self-consistent but not consistent with sanity. 25 | Instant minimumExpected = Instant.FromUtc(2024, 8, 1, 0, 0); 26 | Instant maximumExpected = Instant.FromUtc(2030, 1, 1, 0, 0); 27 | Instant now = SystemClock.Instance.GetCurrentInstant(); 28 | Assert.Less(minimumExpected.ToUnixTimeTicks(), now.ToUnixTimeTicks()); 29 | Assert.Less(now.ToUnixTimeTicks(), maximumExpected.ToUnixTimeTicks()); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/NodaTime.Test/YearMonthTest.XmlSerialization.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Text; 6 | using NUnit.Framework; 7 | using System; 8 | using System.Collections.Generic; 9 | 10 | namespace NodaTime.Test 11 | { 12 | public partial class YearMonthTest 13 | { 14 | [Test] 15 | public void XmlSerialization_Iso() 16 | { 17 | var value = new YearMonth(2013, 4); 18 | TestHelper.AssertXmlRoundtrip(value, "2013-04"); 19 | } 20 | 21 | [Test] 22 | public void XmlSerialization_NonIso() 23 | { 24 | var value = new YearMonth(2013, 4, CalendarSystem.Julian); 25 | TestHelper.AssertXmlRoundtrip(value, "2013-04"); 26 | } 27 | 28 | [Test] 29 | [TestCase("2013-06", typeof(KeyNotFoundException), Description = "Unknown calendar system")] 30 | [TestCase("2013-15", typeof(UnparsableValueException), Description = "Invalid month")] 31 | public void XmlSerialization_Invalid(string xml, Type expectedExceptionType) 32 | { 33 | TestHelper.AssertXmlInvalid(xml, expectedExceptionType); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/NodaTime.Test/CalendarSystemTest.Era.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Calendars; 6 | using NUnit.Framework; 7 | 8 | namespace NodaTime.Test 9 | { 10 | public partial class CalendarSystemTest 11 | { 12 | private static readonly CalendarSystem CopticCalendar = CalendarSystem.Coptic; 13 | 14 | // Tests using CopticCalendar as a simple example which doesn't override anything. 15 | [Test] 16 | public void GetAbsoluteYear() 17 | { 18 | Assert.AreEqual(5, CopticCalendar.GetAbsoluteYear(5, Era.AnnoMartyrum)); 19 | // Prove it's right... 20 | LocalDate localDate = new LocalDate(5, 1, 1, CopticCalendar); 21 | Assert.AreEqual(5, localDate.Year); 22 | Assert.AreEqual(5, localDate.YearOfEra); 23 | Assert.AreEqual(Era.AnnoMartyrum, localDate.Era); 24 | } 25 | 26 | [Test] 27 | public void GetMinYearOfEra() 28 | { 29 | Assert.AreEqual(1, CopticCalendar.GetMinYearOfEra(Era.AnnoMartyrum)); 30 | } 31 | 32 | [Test] 33 | public void GetMaxYearOfEra() 34 | { 35 | Assert.AreEqual(CopticCalendar.MaxYear, CopticCalendar.GetMaxYearOfEra(Era.AnnoMartyrum)); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NodaTime.TzdbCompiler/Tzdb/MissingTokenException.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime.TzdbCompiler.Tzdb 8 | { 9 | /// 10 | /// Thrown when an expected token is missing from the token stream. 11 | /// 12 | public class MissingTokenException : Exception 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// The name. 18 | public MissingTokenException(string name) : this(name, $"Missing token {name}") 19 | { 20 | } 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | /// The name. 26 | /// The message. 27 | public MissingTokenException(string name, string message) : base(message) 28 | { 29 | Name = name; 30 | } 31 | 32 | /// 33 | /// Gets or sets the name of the missing token 34 | /// 35 | /// The token name. 36 | public string Name { get; private set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NodaTime.TzdbCompiler/Tzdb/IoExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | 9 | namespace NodaTime.TzdbCompiler.Tzdb 10 | { 11 | /// 12 | /// IO-related extension methods 13 | /// 14 | internal static class IoExtensions 15 | { 16 | internal static IEnumerable ReadLines(this Stream stream) => ReadLines(new StreamReader(stream)); 17 | 18 | internal static IEnumerable ReadLines(this TextReader reader) 19 | { 20 | string? line; 21 | while ((line = reader.ReadLine()) != null) 22 | { 23 | yield return line; 24 | } 25 | } 26 | 27 | internal static IEnumerable ReadLines(Func readerProvider) 28 | { 29 | using (var reader = readerProvider()) 30 | { 31 | string? line; 32 | while ((line = reader.ReadLine()) != null) 33 | { 34 | yield return line; 35 | } 36 | } 37 | } 38 | 39 | 40 | internal static IEnumerable ReadLines(this FileSource source, string name) => ReadLines(() => new StreamReader(source.Open(name))); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/NodaTime.Test/TimeZones/TransitionTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.TimeZones; 6 | using NUnit.Framework; 7 | 8 | namespace NodaTime.Test.TimeZones 9 | { 10 | public class TransitionTest 11 | { 12 | [Test] 13 | public void Equality() 14 | { 15 | var equal1 = new Transition(Instant.FromUnixTimeSeconds(100), Offset.FromHours(1)); 16 | var equal2 = new Transition(Instant.FromUnixTimeSeconds(100), Offset.FromHours(1)); 17 | var unequal1 = new Transition(Instant.FromUnixTimeSeconds(101), Offset.FromHours(1)); 18 | var unequal2 = new Transition(Instant.FromUnixTimeSeconds(100), Offset.FromHours(2)); 19 | TestHelper.TestEqualsStruct(equal1, equal2, unequal1); 20 | TestHelper.TestEqualsStruct(equal1, equal2, unequal2); 21 | TestHelper.TestOperatorEquality(equal1, equal2, unequal1); 22 | TestHelper.TestOperatorEquality(equal1, equal2, unequal2); 23 | } 24 | 25 | [Test] 26 | public void TransitionToString() 27 | { 28 | var transition = new Transition(Instant.FromUtc(2017, 8, 25, 15, 26, 30), Offset.FromHours(1)); 29 | Assert.AreEqual("Transition to +01 at 2017-08-25T15:26:30Z", transition.ToString()); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Editor backups and temporary files 2 | *~ 3 | *.bak 4 | *.swp 5 | 6 | # IDE-generated files 7 | *.suo 8 | *.user 9 | *.sln.cache 10 | .vs 11 | .vscode 12 | .idea 13 | 14 | # IDE add-ins 15 | *.dotCover 16 | *.ncrunchproject 17 | *.ncrunchsolution 18 | _NCrunch* 19 | .resharper 20 | *.ReSharper 21 | _ReSharper* 22 | StyleCop.Cache 23 | .cr 24 | 25 | # Auto-created thumbnails 26 | Thumbs.db 27 | 28 | # Build output directories (anywhere) 29 | **/bin/ 30 | **/obj/ 31 | 32 | # NUnit output 33 | TestResult.xml 34 | 35 | # Output from build steps 36 | /build/tmp/** 37 | 38 | # Sandcastle per-user settings 39 | /build/NodaTime.shfbproj_* 40 | /build/NodaTime-Pcl.shfbproj_* 41 | 42 | # Generated web site 43 | /www/_site/** 44 | 45 | # Temporary build output directories 46 | /build/tmp 47 | /build/releasebuild 48 | 49 | # Local copy of benchmark data and Mercurial/Git logs, used for testing the dynamic part of the web site 50 | /src/NodaTime.Web/benchmarkdata/** 51 | /src/NodaTime.Web/hg-log.xml 52 | /src/NodaTime.Web/git-log.txt 53 | 54 | # Roslyn temporary files 55 | /src/*.sln.ide/** 56 | 57 | # BenchmarkDotNet output 58 | BenchmarkDotNet.Artifacts 59 | 60 | # Packages installed during the build 61 | packages 62 | coverage 63 | 64 | # Local files 65 | src/NodaTime.Web/docfx 66 | src/NodaTime.Web/benchmarks 67 | build/history 68 | 69 | # If coverage fails, we don't want to add the pinning global.json 70 | # file into source control 71 | src/NodaTime.Test/global.json -------------------------------------------------------------------------------- /src/NodaTime.Test/TimeZones/EtcTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.TimeZones; 6 | using NUnit.Framework; 7 | 8 | namespace NodaTime.Test.TimeZones 9 | { 10 | /// 11 | /// Tests for fixed "Etc/GMT+x" zones. These just test that the time zones are built 12 | /// appropriately; FixedDateTimeZoneTest takes care of the rest. 13 | /// 14 | public class EtcTest 15 | { 16 | [Test] 17 | public void FixedEasternZone() 18 | { 19 | string id = "Etc/GMT+5"; 20 | var zone = DateTimeZoneProviders.Tzdb[id]; 21 | Assert.AreEqual(id, zone.Id); 22 | Assert.IsInstanceOf(zone); 23 | FixedDateTimeZone fixedZone = (FixedDateTimeZone)zone; 24 | Assert.AreEqual(Offset.FromHours(-5), fixedZone.Offset); 25 | } 26 | 27 | [Test] 28 | public void FixedWesternZone() 29 | { 30 | string id = "Etc/GMT-4"; 31 | var zone = DateTimeZoneProviders.Tzdb[id]; 32 | Assert.AreEqual(id, zone.Id); 33 | Assert.IsInstanceOf(zone); 34 | FixedDateTimeZone fixedZone = (FixedDateTimeZone)zone; 35 | Assert.AreEqual(Offset.FromHours(4), fixedZone.Offset); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Testing/Extensions/LocalDateConstructionTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | using static NodaTime.Testing.Extensions.LocalDateConstruction; 7 | 8 | namespace NodaTime.Test.Testing.Extensions 9 | { 10 | public class LocalDateConstructionTest 11 | { 12 | [Test] 13 | public void Construction() 14 | { 15 | Assert.AreEqual(new LocalDate(2017, 1, 18), 18.January(2017)); 16 | Assert.AreEqual(new LocalDate(2017, 2, 18), 18.February(2017)); 17 | Assert.AreEqual(new LocalDate(2017, 3, 18), 18.March(2017)); 18 | Assert.AreEqual(new LocalDate(2017, 4, 18), 18.April(2017)); 19 | Assert.AreEqual(new LocalDate(2017, 5, 18), 18.May(2017)); 20 | Assert.AreEqual(new LocalDate(2017, 6, 18), 18.June(2017)); 21 | Assert.AreEqual(new LocalDate(2017, 7, 18), 18.July(2017)); 22 | Assert.AreEqual(new LocalDate(2017, 8, 18), 18.August(2017)); 23 | Assert.AreEqual(new LocalDate(2017, 9, 18), 18.September(2017)); 24 | Assert.AreEqual(new LocalDate(2017, 10, 18), 18.October(2017)); 25 | Assert.AreEqual(new LocalDate(2017, 11, 18), 18.November(2017)); 26 | Assert.AreEqual(new LocalDate(2017, 12, 18), 18.December(2017)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/BclTests/UtcDateTimeBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using BenchmarkDotNet.Attributes; 7 | 8 | namespace NodaTime.Benchmarks.BclTests 9 | { 10 | [Category("BCL")] 11 | public class UtcDateTimeBenchmarks 12 | { 13 | private readonly DateTime sample = new DateTime(2009, 12, 26, 10, 8, 30, DateTimeKind.Utc); 14 | 15 | [Benchmark] 16 | public DateTime Construction() => new DateTime(2009, 12, 26, 10, 8, 30, DateTimeKind.Utc); 17 | 18 | [Benchmark] 19 | public int Year() => sample.Year; 20 | 21 | [Benchmark] 22 | public int Month() => sample.Month; 23 | 24 | [Benchmark] 25 | public int DayOfMonth() => sample.Day; 26 | 27 | [Benchmark] 28 | public DayOfWeek DayOfWeek() => sample.DayOfWeek; 29 | 30 | [Benchmark] 31 | public int DayOfYear() => sample.DayOfYear; 32 | 33 | [Benchmark] 34 | public int Hour() => sample.Hour; 35 | 36 | [Benchmark] 37 | public int Minute() => sample.Minute; 38 | 39 | [Benchmark] 40 | public int Second() => sample.Second; 41 | 42 | [Benchmark] 43 | public int Millisecond() => sample.Millisecond; 44 | 45 | [Benchmark] 46 | public DateTime ToLocalTime() => sample.ToLocalTime(); 47 | } 48 | } -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks.Custom/ConcurrentPatternFormat.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Text; 6 | using System.Threading; 7 | 8 | namespace NodaTime.Benchmarks.Custom; 9 | 10 | internal class ConcurrentPatternFormat : ConcurrencyCommandBase 11 | { 12 | private ConcurrentPatternFormat(int threadCount, Duration executionTime) : base(threadCount, executionTime) 13 | { 14 | } 15 | 16 | protected override void DoWork() 17 | { 18 | var pattern = LocalTimePattern.CreateWithInvariantCulture("HH:mm:ss"); 19 | LocalTime localTime = new LocalTime(23, 15, 20); 20 | while (Interlocked.Add(ref iterations, ChunkSize) > 0) 21 | { 22 | for (int i = 0; i < ChunkSize; i++) 23 | { 24 | pattern.Format(localTime); 25 | } 26 | } 27 | } 28 | 29 | internal static void Execute(string[] args) 30 | { 31 | if (args.Length != 2) 32 | { 33 | throw new ConfigurationException("Command arguments: "); 34 | } 35 | 36 | int threadCount = int.Parse(args[0]); 37 | int executionTimeSeconds = int.Parse(args[1]); 38 | var command = new ConcurrentPatternFormat(threadCount, Duration.FromSeconds(executionTimeSeconds)); 39 | command.Execute(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/Text/LocalTimePatternBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using NodaTime.Text; 7 | 8 | namespace NodaTime.Benchmarks.NodaTimeTests.Text 9 | { 10 | [Category("Text")] 11 | public class LocalTimePatternBenchmarks 12 | { 13 | private static readonly LocalTime SampleLocalTimeToSecond = new LocalTime(15, 12, 10); 14 | private static readonly LocalTime SampleLocalTimeToNanos = LocalTime.FromHourMinuteSecondNanosecond(15, 12, 10, 123456789L); 15 | private static readonly string SampleIsoFormattedTime = "15:12:10"; 16 | private static readonly string SampleIsoFormattedTimeWithNanos = "15:12:10.123456789"; 17 | 18 | [Benchmark] 19 | public void ExtendedIso_Format() => 20 | LocalTimePattern.ExtendedIso.Format(SampleLocalTimeToNanos); 21 | 22 | [Benchmark] 23 | public void ExtendedIso_Parse() => 24 | LocalTimePattern.ExtendedIso.Parse(SampleIsoFormattedTimeWithNanos); 25 | 26 | [Benchmark] 27 | public void IsoPatternToSecond_Format() => 28 | LocalTimePattern.GeneralIso.Format(SampleLocalTimeToSecond); 29 | 30 | [Benchmark] 31 | public void IsoPatternToSecond_Parse() => 32 | LocalTimePattern.GeneralIso.Parse(SampleIsoFormattedTime); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Extensions/DateTimeOffsetExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Extensions; 6 | using NUnit.Framework; 7 | using System; 8 | 9 | namespace NodaTime.Test.Extensions 10 | { 11 | public class DateTimeOffsetExtensionsTest 12 | { 13 | private static readonly DateTimeOffset Sample = new DateTimeOffset(2017, 8, 21, 12, 46, 13, TimeSpan.FromHours(1)); 14 | 15 | [Test] 16 | public void ToOffsetDateTime() 17 | { 18 | var expected = new OffsetDateTime(new LocalDateTime(2017, 8, 21, 12, 46, 13), Offset.FromHours(1)); 19 | var actual = Sample.ToOffsetDateTime(); 20 | Assert.AreEqual(expected, actual); 21 | } 22 | 23 | [Test] 24 | public void ToZonedDateTime() 25 | { 26 | var expected = new LocalDateTime(2017, 8, 21, 12, 46, 13).InZoneStrictly(DateTimeZone.ForOffset(Offset.FromHours(1))); 27 | var actual = Sample.ToZonedDateTime(); 28 | Assert.AreEqual(expected, actual); 29 | } 30 | 31 | [Test] 32 | public void ToInstant() 33 | { 34 | // Note hour of 11 rather than 12. 35 | var expected = Instant.FromUtc(2017, 8, 21, 11, 46, 13); 36 | var actual = Sample.ToInstant(); 37 | Assert.AreEqual(expected, actual); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/NodaTime.Test/YearMonthTest.BasicProperties.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Calendars; 6 | using NUnit.Framework; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | 11 | namespace NodaTime.Test 12 | { 13 | public partial class YearMonthTest 14 | { 15 | [Test] 16 | public void Properties() 17 | { 18 | // Some of these are covered in other tests too, but it doesn't hurt 19 | // to repeat ourselves here. 20 | var yearMonth = new YearMonth(2000, 1); 21 | Assert.AreEqual(2000, yearMonth.Year); 22 | Assert.AreEqual(1, yearMonth.Month); 23 | Assert.AreEqual(CalendarSystem.Iso, yearMonth.Calendar); 24 | Assert.AreEqual(2000, yearMonth.YearOfEra); 25 | Assert.AreEqual(Era.Common, yearMonth.Era); 26 | 27 | Assert.AreEqual(new LocalDate(2000, 1, 1), yearMonth.StartDate); 28 | Assert.AreEqual(new LocalDate(2000, 1, 31), yearMonth.EndDate); 29 | } 30 | 31 | [Test] 32 | public void ToDateInterval() 33 | { 34 | var yearMonth = new YearMonth(2000, 1); 35 | 36 | var interval = new DateInterval(new LocalDate(2000, 1, 1), new LocalDate(2000, 1, 31)); 37 | Assert.AreEqual(interval, yearMonth.ToDateInterval()); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks.Custom/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | // This program is for any custom benchmarks that can't easily be tested with BenchmarkDotNet. 6 | // (Where things become possible over time, we should migrate benchmarks to BenchmarkDotNet.) 7 | // These benchmarks are not run or recorded automatically. 8 | 9 | using NodaTime.Benchmarks.Custom; 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | 14 | Dictionary> commands = new() 15 | { 16 | { "concurrent-tostring", ConcurrentToString.Execute }, 17 | { "concurrent-patternformat", ConcurrentPatternFormat.Execute }, 18 | { "concurrent-newstring", ConcurrentNewString.Execute }, 19 | { "concurrent-noop", ConcurrentNoOp.Execute }, 20 | }; 21 | 22 | if (args.Length < 1) 23 | { 24 | Console.WriteLine("Please specify a command:"); 25 | Console.WriteLine(string.Join(" ", commands.Keys.OrderBy(x => x))); 26 | return 1; 27 | } 28 | 29 | if (!commands.TryGetValue(args[0], out var command)) 30 | { 31 | Console.WriteLine("Unknown command. Available commands:"); 32 | Console.WriteLine(string.Join(" ", commands.Keys.OrderBy(x => x))); 33 | return 1; 34 | } 35 | 36 | try 37 | { 38 | command.Invoke(args.Skip(1).ToArray()); 39 | } 40 | catch (ConfigurationException e) 41 | { 42 | Console.WriteLine(e.Message); 43 | return 1; 44 | } 45 | return 0; 46 | -------------------------------------------------------------------------------- /src/NodaTime.Test/coverageparams.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | c:/Program Files/dotnet/dotnet.exe 8 | test --no-build -c Release 9 | . 10 | 11 | 12 | 13 | NodaTime 14 | 15 | 16 | NodaTime.Testing 17 | 18 | 19 | 20 | 21 | JetBrains.Annotations.* 22 | 23 | 24 | NodaTime.Annotations.* 25 | 26 | 27 | 28 | NodaTime.Utility.Preconditions 29 | Debug* 30 | 31 | 32 | 33 | 34 | System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute 35 | System.Diagnostics.DebuggerNonUserCodeAttribute 36 | 37 | ../../coverage/NodaTime.dvcr 38 | 39 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Calendars/EraTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Calendars; 6 | using NodaTime.Globalization; 7 | using NUnit.Framework; 8 | using System.Collections.Generic; 9 | using System.Globalization; 10 | using System.Linq; 11 | using System.Reflection; 12 | 13 | namespace NodaTime.Test.Calendars 14 | { 15 | public class EraTest 16 | { 17 | private static readonly IEnumerable> Eras = typeof(Era).GetTypeInfo() 18 | .DeclaredProperties // TODO: Only static and public ones... 19 | .Where(property => property.PropertyType == typeof(Era)) 20 | .Select(property => new NamedWrapper((Era) property.GetValue(null, null)!, property.Name)); 21 | 22 | [Test] 23 | [TestCaseSource(nameof(Eras))] 24 | public void ResourcePresence(NamedWrapper eraWrapper) 25 | { 26 | var era = eraWrapper.Value; 27 | var valueByName = PatternResources.ResourceManager.GetString(era.ResourceIdentifier, CultureInfo.InvariantCulture); 28 | Assert.NotNull(valueByName, $"Missing resource for {era.ResourceIdentifier}"); 29 | } 30 | 31 | [Test] 32 | [TestCaseSource(nameof(Eras))] 33 | public void ToStringReturnsName(NamedWrapper eraWrapper) 34 | { 35 | var era = eraWrapper.Value; 36 | Assert.AreEqual(era.Name, era.ToString()); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Calendars/IsoCalendarSystemTest.FieldValidation.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using NUnit.Framework; 7 | 8 | namespace NodaTime.Test.Calendars 9 | { 10 | public partial class IsoCalendarSystemTest 11 | { 12 | // These tests assume that if the method doesn't throw, it's doing the right thing - this 13 | // is all tested elsewhere. 14 | [Test] 15 | public void ValidateYearMonthDay_AllValues_ValidValuesDoesntThrow() 16 | { 17 | Iso.ValidateYearMonthDay(20, 2, 20); 18 | } 19 | 20 | [Test] 21 | public void ValidateYearMonthDay_InvalidYear_Throws() 22 | { 23 | Assert.Throws(() => Iso.ValidateYearMonthDay(50000, 2, 20)); 24 | } 25 | 26 | [Test] 27 | public void GetLocalInstant_InvalidMonth_Throws() 28 | { 29 | Assert.Throws(() => Iso.ValidateYearMonthDay(2010, 13, 20)); 30 | } 31 | 32 | [Test] 33 | public void GetLocalInstant_29thOfFebruaryInNonLeapYear_Throws() 34 | { 35 | Assert.Throws(() => Iso.ValidateYearMonthDay(2010, 2, 29)); 36 | } 37 | 38 | [Test] 39 | public void GetLocalInstant_29thOfFebruaryInLeapYear_DoesntThrow() 40 | { 41 | Iso.ValidateYearMonthDay(2012, 2, 29); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/NodaTime.TzdbCompiler.Test/Tzdb/DateTimeZoneBuilderTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | using NodaTime.TimeZones; 7 | using NodaTime.TzdbCompiler.Tzdb; 8 | using System.Collections.Generic; 9 | 10 | namespace NodaTime.TzdbCompiler.Test.Tzdb 11 | { 12 | /// 13 | /// Tests for DateTimeZoneBuilder; currently only scant coverage based on bugs which have 14 | /// previously been found. 15 | /// 16 | public class DateTimeZoneBuilderTest 17 | { 18 | [Test] 19 | public void FixedZone_Western() 20 | { 21 | var offset = Offset.FromHours(-5); 22 | var rules = new List { new ZoneRuleSet("GMT+5", offset, Offset.Zero, int.MaxValue, null) }; 23 | var zone = DateTimeZoneBuilder.Build("GMT+5", rules); 24 | FixedDateTimeZone fixedZone = (FixedDateTimeZone)zone; 25 | Assert.AreEqual(offset, fixedZone.Offset); 26 | } 27 | 28 | [Test] 29 | public void FixedZone_Eastern() 30 | { 31 | var offset = Offset.FromHours(5); 32 | var rules = new List { new ZoneRuleSet("GMT-5", offset, Offset.Zero, int.MaxValue, null) }; 33 | var zone = DateTimeZoneBuilder.Build("GMT-5", rules); 34 | FixedDateTimeZone fixedZone = (FixedDateTimeZone)zone; 35 | Assert.AreEqual(offset, fixedZone.Offset); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/Text/PeriodPatternBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using NodaTime.Text; 7 | 8 | namespace NodaTime.Benchmarks.NodaTimeTests.Text 9 | { 10 | [Category("Text")] 11 | public class PeriodPatternBenchmarks 12 | { 13 | private static readonly Period SamplePeriod = new PeriodBuilder 14 | { 15 | Years = 100, Months = 1, Days = 10, Hours = 12, Minutes = 35, Seconds = 12, Milliseconds = 123, Ticks = 4567 16 | }.Build(); 17 | 18 | private static readonly string NormalizedText = PeriodPattern.NormalizingIso.Format(SamplePeriod); 19 | private static readonly string RoundtripText = PeriodPattern.Roundtrip.Format(SamplePeriod); 20 | 21 | [Benchmark] 22 | public void ParseNormalized() 23 | { 24 | PeriodPattern.NormalizingIso.Parse(NormalizedText).GetValueOrThrow(); 25 | } 26 | 27 | [Benchmark] 28 | public void ParseRoundtrip() 29 | { 30 | PeriodPattern.Roundtrip.Parse(RoundtripText).GetValueOrThrow(); 31 | } 32 | 33 | [Benchmark] 34 | public void FormatNormalized() 35 | { 36 | PeriodPattern.NormalizingIso.Format(SamplePeriod); 37 | } 38 | 39 | [Benchmark] 40 | public void FormatRoundtrip() 41 | { 42 | PeriodPattern.Roundtrip.Format(SamplePeriod); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/NodaTime.Test/LocalTimeTest.Conversion.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using System.Globalization; 7 | using System.Linq; 8 | using NUnit.Framework; 9 | 10 | namespace NodaTime.Test 11 | { 12 | public partial class LocalTimeTest 13 | { 14 | 15 | #if NET6_0_OR_GREATER 16 | [Test] 17 | public void ToTimeOnly_OnTickBoundary() 18 | { 19 | var localTime = new LocalTime(12, 34, 56, 300).PlusTicks(4567); 20 | var expected = new TimeOnly(12, 34, 56, 300).Add(TimeSpan.FromTicks(4567)); 21 | var actual = localTime.ToTimeOnly(); 22 | Assert.AreEqual(expected, actual); 23 | } 24 | 25 | [Test] 26 | public void ToTimeOnly_RoundsDown() 27 | { 28 | var localTime = new LocalTime(12, 34, 56, 300).PlusTicks(4567).PlusNanoseconds(89); 29 | var expected = new TimeOnly(12, 34, 56, 300).Add(TimeSpan.FromTicks(4567)); 30 | var actual = localTime.ToTimeOnly(); 31 | Assert.AreEqual(expected, actual); 32 | } 33 | 34 | [Test] 35 | public void FromTimeOnly() 36 | { 37 | var timeOnly = new TimeOnly(12, 34, 56, 300).Add(TimeSpan.FromTicks(4567)); 38 | var expected = new LocalTime(12, 34, 56, 300).PlusTicks(4567); 39 | var actual = LocalTime.FromTimeOnly(timeOnly); 40 | Assert.AreEqual(expected, actual); 41 | } 42 | #endif 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/NodaTime/IClock.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime 8 | { 9 | /// 10 | /// Represents a clock which can return the current time as an . 11 | /// 12 | /// 13 | /// is intended for use anywhere you need to have access to the current time. 14 | /// Although it's not strictly incorrect to call SystemClock.Instance.GetCurrentInstant() directly, 15 | /// in the same way as you might call , it's strongly discouraged 16 | /// as a matter of style for production code. We recommend providing an instance of 17 | /// to anything that needs it, which allows you to write tests using the fake clock in the NodaTime.Testing 18 | /// assembly (or your own implementation). 19 | /// 20 | /// 21 | /// All implementations in Noda Time are thread-safe; custom implementations 22 | /// should be thread-safe too. See the thread safety section of the user guide for more information. 23 | /// 24 | public interface IClock 25 | { 26 | /// 27 | /// Gets the current on the time line according to this clock. 28 | /// 29 | /// The current instant on the time line according to this clock. 30 | Instant GetCurrentInstant(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Calendars/GregorianCalendarSystemTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Calendars; 6 | using NUnit.Framework; 7 | 8 | namespace NodaTime.Test.Calendars 9 | { 10 | public class GregorianCalendarSystemTest 11 | { 12 | [Test] 13 | public void LeapYears() 14 | { 15 | var calendar = CalendarSystem.Gregorian; 16 | Assert.IsFalse(calendar.IsLeapYear(1900)); 17 | Assert.IsFalse(calendar.IsLeapYear(1901)); 18 | Assert.IsTrue(calendar.IsLeapYear(1904)); 19 | Assert.IsTrue(calendar.IsLeapYear(1996)); 20 | Assert.IsTrue(calendar.IsLeapYear(2000)); 21 | Assert.IsFalse(calendar.IsLeapYear(2100)); 22 | Assert.IsTrue(calendar.IsLeapYear(2400)); 23 | } 24 | 25 | [Test] 26 | public void EraProperty() 27 | { 28 | CalendarSystem calendar = CalendarSystem.Gregorian; 29 | LocalDateTime startOfEra = new LocalDateTime(1, 1, 1, 0, 0, 0, calendar); 30 | Assert.AreEqual(Era.Common, startOfEra.Era); 31 | Assert.AreEqual(Era.BeforeCommon, startOfEra.PlusTicks(-1).Era); 32 | } 33 | 34 | [Test] 35 | public void AddMonths_BoundaryCondition() 36 | { 37 | var start = new LocalDate(2017, 8, 20); 38 | var end = start.PlusMonths(-19); 39 | var expected = new LocalDate(2016, 1, 20); 40 | Assert.AreEqual(expected, end); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/NodaTime/TimeZones/InvalidDateTimeZoneSourceException.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Annotations; 6 | using System; 7 | 8 | // Standard exception constructors. 9 | // This exception is expected to be constructed within the library. 10 | // There are never any inner exceptions, and we always *do* have a message. 11 | #pragma warning disable CA1032 12 | 13 | namespace NodaTime.TimeZones 14 | { 15 | /// 16 | /// Exception thrown to indicate that a time zone source has violated the contract of . 17 | /// This exception is primarily intended to be thrown from , and only in the face of a buggy 18 | /// source; user code should not usually need to be aware of this or catch it. 19 | /// 20 | /// Any public static members of this type are thread safe. Any instance members are not guaranteed to be thread safe. 21 | /// See the thread safety section of the user guide for more information. 22 | /// 23 | [Mutable] // Exception itself is mutable 24 | public sealed class InvalidDateTimeZoneSourceException : Exception 25 | { 26 | /// 27 | /// Creates a new instance with the given message. 28 | /// 29 | /// The message for the exception. 30 | public InvalidDateTimeZoneSourceException(string message) 31 | : base(message) 32 | { 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/NodaTime/Annotations/ImmutableAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime.Annotations 8 | { 9 | /// 10 | /// Indicates that a type is immutable. After construction, the publicly visible 11 | /// state of the object will not change. 12 | /// 13 | /// 14 | ///

15 | /// This attribute only applies to types, not fields: 16 | /// it's entirely feasible to have a readonly field of a mutable type, or a read/write 17 | /// field of an immutable type. In such cases for reference types (classes and interfaces) 18 | /// it's important to distinguish between the value of the variable (a reference) and the 19 | /// object it refers to. Value types are more complicated as in some cases the compiler 20 | /// will copy values before operating on them; however as all value types in Noda Time are 21 | /// immutable (aside from explicitly implemented serialization operations) this rarely causes 22 | /// an issue. 23 | ///

24 | ///

25 | /// Some types may be publicly immutable, but contain privately mutable 26 | /// aspects, e.g. caches. If it proves to be useful to indicate the kind of 27 | /// immutability we're implementing, we can add an appropriate property to this 28 | /// attribute. 29 | ///

30 | ///
31 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] 32 | internal sealed class ImmutableAttribute : Attribute 33 | { 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/NodaTime/Calendars/CopticYearMonthDayCalculator.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime.Calendars 6 | { 7 | internal sealed class CopticYearMonthDayCalculator : FixedMonthYearMonthDayCalculator 8 | { 9 | internal CopticYearMonthDayCalculator() 10 | : base(1, 9715, -615558) 11 | { 12 | } 13 | 14 | protected override int CalculateStartOfYearDays(int year) 15 | { 16 | // Unix epoch is 1970-01-01 Gregorian which is 1686-04-23 Coptic. 17 | // Calculate relative to the nearest leap year and account for the 18 | // difference later. 19 | 20 | int relativeYear = year - 1687; 21 | int leapYears; 22 | if (relativeYear <= 0) 23 | { 24 | // Add 3 before shifting right since /4 and >>2 behave differently 25 | // on negative numbers. 26 | leapYears = (relativeYear + 3) >> 2; 27 | } 28 | else 29 | { 30 | leapYears = relativeYear >> 2; 31 | // For post 1687 an adjustment is needed as jan1st is before leap day 32 | if (!IsLeapYear(year)) 33 | { 34 | leapYears++; 35 | } 36 | } 37 | 38 | int ret = relativeYear * 365 + leapYears; 39 | 40 | // Adjust to account for difference between 1687-01-01 and 1686-04-23. 41 | return ret + (365 - 112); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Utility/TickArithmeticTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using NodaTime.Utility; 5 | using NUnit.Framework; 6 | 7 | namespace NodaTime.Test.Utility 8 | { 9 | public class TickArithmeticTest 10 | { 11 | [Test] 12 | [TestCase(long.MinValue)] 13 | [TestCase(-NodaConstants.TicksPerDay - 1)] 14 | [TestCase(-NodaConstants.TicksPerDay)] 15 | [TestCase(-NodaConstants.TicksPerDay + 1)] 16 | [TestCase(-1)] 17 | [TestCase(0)] 18 | [TestCase(1)] 19 | [TestCase(NodaConstants.TicksPerDay - 1)] 20 | [TestCase(NodaConstants.TicksPerDay)] 21 | [TestCase(NodaConstants.TicksPerDay + 1)] 22 | [TestCase(long.MaxValue)] 23 | public void TicksToDaysAndTickOfDayAndBack(long ticks) 24 | { 25 | int days = TickArithmetic.TicksToDaysAndTickOfDay(ticks, out long tickOfDay); 26 | 27 | Assert.AreEqual(ticks, TickArithmetic.DaysAndTickOfDayToTicks(days, tickOfDay)); 28 | } 29 | 30 | [Test] 31 | public void DaysAndTickOfDayToTicksUncheckedBoundaries() 32 | { 33 | // Only a useful test under debug, but this proves that the arithmetic won't overflow when used from 34 | // LocalDateTime or Instant. (In debug mode, we have 35 | TickArithmetic.BoundedDaysAndTickOfDayToTicks(CalendarSystem.Iso.MinDays, 0); 36 | TickArithmetic.BoundedDaysAndTickOfDayToTicks(CalendarSystem.Iso.MaxDays, NodaConstants.TicksPerDay - 1); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Annotations/SecurityTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Security; 10 | 11 | namespace NodaTime.Test.Annotations 12 | { 13 | public class SecurityTest 14 | { 15 | [Test] 16 | public void SecurityAttributesOnInterfaceImplementations() 17 | { 18 | var violations = new List(); 19 | 20 | foreach (var type in typeof(Instant).Assembly.DefinedTypes.Where(type => !type.IsInterface)) 21 | { 22 | foreach (var iface in type.ImplementedInterfaces) 23 | { 24 | var map = type.GetRuntimeInterfaceMap(iface); 25 | var methodCount = map.InterfaceMethods.Length; 26 | for (int i = 0; i < methodCount; i++) 27 | { 28 | if (map.TargetMethods[i].DeclaringType?.GetTypeInfo() == type && 29 | map.InterfaceMethods[i].IsDefined(typeof(SecurityCriticalAttribute), false) && 30 | !map.TargetMethods[i].IsDefined(typeof(SecurityCriticalAttribute), false)) 31 | { 32 | violations.Add($"{type.FullName}/{map.TargetMethods[i].Name}"); 33 | } 34 | } 35 | } 36 | } 37 | TestHelper.AssertNoFailures(violations, v => v); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/NodaTime.Tools.ValidateHistoricalNzd/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.TimeZones; 6 | using System; 7 | using System.IO; 8 | using System.Net.Http; 9 | using System.Threading.Tasks; 10 | 11 | namespace NodaTime.Tools.ValidateHistoricalNzd 12 | { 13 | class Program 14 | { 15 | private static async Task Main() 16 | { 17 | var httpClient = new HttpClient(); 18 | var allUrlsText = await httpClient.GetStringAsync("https://nodatime.org/tzdb/index.txt"); 19 | var urls = allUrlsText.Replace("\r", "").Split("\n", StringSplitOptions.RemoveEmptyEntries); 20 | bool success = true; 21 | foreach (var url in urls) 22 | { 23 | success &= await ValidateAsync(httpClient, url); 24 | } 25 | return success ? 0 : 1; 26 | } 27 | 28 | private static async Task ValidateAsync(HttpClient httpClient, string url) 29 | { 30 | try 31 | { 32 | Console.WriteLine($"Validating {url}"); 33 | byte[] data = await httpClient.GetByteArrayAsync(url); 34 | var source = TzdbDateTimeZoneSource.FromStream(new MemoryStream(data)); 35 | source.Validate(); 36 | return true; 37 | } 38 | catch (Exception e) 39 | { 40 | Console.WriteLine($"{e.GetType().Name}: {e.Message}"); 41 | return false; 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Text/Patterns/PatternFieldsExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Text.Patterns; 6 | using NUnit.Framework; 7 | using static NodaTime.Text.Patterns.PatternFields; 8 | 9 | namespace NodaTime.Test.Text 10 | { 11 | public class PatternFieldsExtensionsTest 12 | { 13 | [Test] 14 | public void IsUsed_NoMatch() 15 | { 16 | Assert.IsFalse((Hours12 | Minutes).HasAny(Hours24)); 17 | } 18 | 19 | [Test] 20 | public void IsUsed_SingleValueMatch() 21 | { 22 | Assert.IsTrue(Hours24.HasAny(Hours24)); 23 | } 24 | 25 | [Test] 26 | public void IsFieldUsed_MultiValueMatch() 27 | { 28 | Assert.IsTrue((Hours24 | Minutes).HasAny(Hours24)); 29 | } 30 | 31 | [Test] 32 | public void AllAreUsed_NoMatch() 33 | { 34 | Assert.IsFalse((Hours12 | Minutes).HasAll(Hours24 | Seconds)); 35 | } 36 | 37 | [Test] 38 | public void AllAreUsed_PartialMatch() 39 | { 40 | Assert.IsFalse((Hours12 | Minutes).HasAll(Hours12 | Seconds)); 41 | } 42 | 43 | [Test] 44 | public void AllAreUsed_CompleteMatch() 45 | { 46 | Assert.IsTrue((Hours12 | Minutes).HasAll(Hours12 | Minutes)); 47 | } 48 | 49 | [Test] 50 | public void AllAreUsed_CompleteMatchWithMore() 51 | { 52 | Assert.IsTrue((Hours24 | Minutes | Hours12).HasAll(Hours24 | Minutes)); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/PacificZonedDateTimeBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | 7 | namespace NodaTime.Benchmarks.NodaTimeTests 8 | { 9 | public class PacificZonedDateTimeBenchmarks 10 | { 11 | private static readonly DateTimeZone Pacific = DateTimeZoneProviders.Tzdb["America/Los_Angeles"]; 12 | private static readonly LocalDateTime SampleLocal = new LocalDateTime(2009, 12, 26, 10, 8, 30); 13 | private static readonly ZonedDateTime SampleZoned = Pacific.AtStrictly(SampleLocal); 14 | 15 | [Benchmark] 16 | public ZonedDateTime Construction() => Pacific.AtStrictly(SampleLocal); 17 | 18 | [Benchmark] 19 | public int Year() => SampleZoned.Year; 20 | 21 | [Benchmark] 22 | public int Month() => SampleZoned.Month; 23 | 24 | [Benchmark] 25 | public int DayOfMonth() => SampleZoned.Day; 26 | 27 | [Benchmark] 28 | public IsoDayOfWeek DayOfWeek() => SampleZoned.DayOfWeek; 29 | 30 | [Benchmark] 31 | public int DayOfYear() => SampleZoned.DayOfYear; 32 | 33 | [Benchmark] 34 | public int Hour() => SampleZoned.Hour; 35 | 36 | [Benchmark] 37 | public int Minute() => SampleZoned.Minute; 38 | 39 | [Benchmark] 40 | public int Second() => SampleZoned.Second; 41 | 42 | [Benchmark] 43 | public int Millisecond() => SampleZoned.Millisecond; 44 | 45 | [Benchmark] 46 | public Instant ToInstant() => SampleZoned.ToInstant(); 47 | } 48 | } -------------------------------------------------------------------------------- /src/NodaTime/Fields/IDatePeriodField.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime.Fields 6 | { 7 | /// 8 | /// General representation of the difference between two dates in a particular time unit, 9 | /// such as "days" or "months". 10 | /// 11 | internal interface IDatePeriodField 12 | { 13 | /// 14 | /// Adds a duration value (which may be negative) to the date. This may not 15 | /// be reversible; for example, adding a month to January 30th will result in 16 | /// February 28th or February 29th. 17 | /// 18 | /// The local date to add to 19 | /// The value to add, in the units of the field 20 | /// The updated local date 21 | LocalDate Add(LocalDate localDate, int value); 22 | 23 | /// 24 | /// Computes the difference between two local dates, as measured in the units 25 | /// of this field, rounding towards zero. This rounding means that 26 | /// unit.Add(start, unit.UnitsBetween(start, end)) always ends up with a date 27 | /// between start and end. (Ideally equal to end, but importantly, it never overshoots.) 28 | /// 29 | /// The start date 30 | /// The end date 31 | /// The difference in the units of this field 32 | int UnitsBetween(LocalDate start, LocalDate end); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/NodaTime/IsoDayOfWeek.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime 6 | { 7 | /// 8 | /// Equates the days of the week with their numerical value according to 9 | /// ISO-8601. This corresponds with System.DayOfWeek except for Sunday, which 10 | /// is 7 in the ISO numbering and 0 in System.DayOfWeek. 11 | /// 12 | public enum IsoDayOfWeek 13 | { 14 | /// 15 | /// Value indicating no day of the week; this will never be returned 16 | /// by any IsoDayOfWeek property, and is not valid as an argument to 17 | /// any method. 18 | /// 19 | None = 0, 20 | /// 21 | /// Value representing Monday (1). 22 | /// 23 | Monday = 1, 24 | /// 25 | /// Value representing Tuesday (2). 26 | /// 27 | Tuesday = 2, 28 | /// 29 | /// Value representing Wednesday (3). 30 | /// 31 | Wednesday = 3, 32 | /// 33 | /// Value representing Thursday (4). 34 | /// 35 | Thursday = 4, 36 | /// 37 | /// Value representing Friday (5). 38 | /// 39 | Friday = 5, 40 | /// 41 | /// Value representing Saturday (6). 42 | /// 43 | Saturday = 6, 44 | /// 45 | /// Value representing Sunday (7). 46 | /// 47 | Sunday = 7 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Calendars/JulianCalendarSystemTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | 7 | namespace NodaTime.Test.Calendars 8 | { 9 | /// 10 | /// Tests for the Julian calendar system via JulianYearMonthDayCalculator. 11 | /// 12 | public partial class JulianCalendarSystemTest 13 | { 14 | private static readonly CalendarSystem Julian = CalendarSystem.Julian; 15 | 16 | /// 17 | /// The Unix epoch is equivalent to December 19th 1969 in the Julian calendar. 18 | /// 19 | [Test] 20 | public void Epoch() 21 | { 22 | LocalDateTime julianEpoch = NodaConstants.UnixEpoch.InZone(DateTimeZone.Utc, Julian).LocalDateTime; 23 | Assert.AreEqual(1969, julianEpoch.Year); 24 | Assert.AreEqual(12, julianEpoch.Month); 25 | Assert.AreEqual(19, julianEpoch.Day); 26 | } 27 | 28 | [Test] 29 | public void LeapYears() 30 | { 31 | Assert.IsTrue(Julian.IsLeapYear(1900)); // No 100 year rule... 32 | Assert.IsFalse(Julian.IsLeapYear(1901)); 33 | Assert.IsTrue(Julian.IsLeapYear(1904)); 34 | Assert.IsTrue(Julian.IsLeapYear(2000)); 35 | Assert.IsTrue(Julian.IsLeapYear(2100)); // No 100 year rule... 36 | Assert.IsTrue(Julian.IsLeapYear(2400)); 37 | // Check 1BC, 5BC etc... 38 | Assert.IsTrue(Julian.IsLeapYear(0)); 39 | Assert.IsTrue(Julian.IsLeapYear(-4)); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/NodaTime/Extensions/TimeSpanExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using System; 5 | 6 | namespace NodaTime.Extensions 7 | { 8 | /// 9 | /// Extension methods for . 10 | /// 11 | public static class TimeSpanExtensions 12 | { 13 | /// 14 | /// Converts a into a . 15 | /// 16 | /// This is a convenience method which calls . 17 | /// The TimeSpan to convert. 18 | /// A Duration representing the same length of time as . 19 | public static Duration ToDuration(this TimeSpan timeSpan) => Duration.FromTimeSpan(timeSpan); 20 | 21 | /// 22 | /// Converts a into an . 23 | /// 24 | /// This is a convenience method which calls . 25 | /// The TimeSpan to convert. 26 | /// An Offset representing the same length of time as . 27 | /// is too large or small to 28 | /// be represented as an Offset. 29 | public static Offset ToOffset(this TimeSpan timeSpan) => Offset.FromTimeSpan(timeSpan); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/NodaTime/Text/Patterns/PatternBclSupport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Globalization; 6 | using System; 7 | 8 | namespace NodaTime.Text.Patterns 9 | { 10 | /// 11 | /// Class providing simple support for the various Parse/TryParse/ParseExact/TryParseExact/Format overloads 12 | /// provided by individual types. 13 | /// 14 | internal sealed class PatternBclSupport 15 | { 16 | private readonly Func> patternParser; 17 | private readonly string defaultFormatPattern; 18 | 19 | internal PatternBclSupport(string defaultFormatPattern, Func> patternParser) 20 | { 21 | this.patternParser = patternParser; 22 | this.defaultFormatPattern = defaultFormatPattern; 23 | } 24 | 25 | internal string Format(T value, string? patternText, IFormatProvider? formatProvider) 26 | { 27 | if (string.IsNullOrEmpty(patternText)) 28 | { 29 | patternText = defaultFormatPattern; 30 | } 31 | NodaFormatInfo formatInfo = NodaFormatInfo.GetInstance(formatProvider); 32 | // Note: string.IsNullOrEmpty isn't annotated in netstandard2.0, hence the use of the 33 | // null-forgiving operator here. *We* know patternText isn't null. 34 | IPattern pattern = patternParser(formatInfo).ParsePattern(patternText!); 35 | return pattern.Format(value); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NodaTime.Demo/OffsetTimeDemo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | 7 | namespace NodaTime.Demo 8 | { 9 | public class OffsetTimeDemo 10 | { 11 | [Test] 12 | public void Construction() 13 | { 14 | OffsetTime offsetTime = Snippet.For(new OffsetTime( 15 | new LocalTime(15, 20, 48), 16 | Offset.FromHours(3))); 17 | 18 | Assert.AreEqual(new LocalTime(15, 20, 48), offsetTime.TimeOfDay); 19 | Assert.AreEqual(Offset.FromHours(3), offsetTime.Offset); 20 | } 21 | 22 | [Test] 23 | public void WithOffset() 24 | { 25 | OffsetTime original = new OffsetTime( 26 | new LocalTime(15, 20, 48), 27 | Offset.FromHours(3)); 28 | 29 | OffsetTime updated = Snippet.For( 30 | original.WithOffset(Offset.FromHours(-3))); 31 | 32 | Assert.AreEqual(original.TimeOfDay, updated.TimeOfDay); 33 | Assert.AreEqual(Offset.FromHours(-3), updated.Offset); 34 | } 35 | 36 | [Test] 37 | public void With() 38 | { 39 | OffsetTime original = new OffsetTime( 40 | new LocalTime(15, 20, 48), 41 | Offset.FromHours(3)); 42 | 43 | OffsetTime updated = Snippet.For( 44 | original.With(x => x.PlusHours(5))); 45 | 46 | Assert.AreEqual(new LocalTime(20, 20, 48), updated.TimeOfDay); 47 | Assert.AreEqual(original.Offset, updated.Offset); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Annotations/PurityTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using JetBrains.Annotations; 9 | using NUnit.Framework; 10 | 11 | namespace NodaTime.Test.Annotations 12 | { 13 | /// 14 | /// Tests for annotations around purity. No sniggering at the back, please. 15 | /// 16 | public class PurityTest 17 | { 18 | [Test] 19 | public void AllPublicStructMethodsArePure() 20 | { 21 | var implicitlyPureNames = new HashSet { "Equals", "GetHashCode", "CompareTo", "ToString" }; 22 | 23 | var impureMethods = typeof(Instant).Assembly 24 | .DefinedTypes 25 | .Where(t => t.IsValueType && (t.IsPublic || t.IsNestedPublic)) 26 | .OrderBy(t => t.Name) 27 | .SelectMany(m => m.DeclaredMethods) 28 | .Where(m => m.IsPublic && !m.IsStatic) 29 | .Where(m => !m.IsSpecialName) // Real methods, not properties 30 | .Where(m => !implicitlyPureNames.Contains(m.Name)) 31 | .Where(m => !m.IsDefined(typeof(PureAttribute))); 32 | 33 | TestHelper.AssertNoFailures(impureMethods, m => $"{m.DeclaringType?.Name}.{m.Name}"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/NodaTime/SystemClock.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Annotations; 6 | using System; 7 | 8 | namespace NodaTime 9 | { 10 | /// 11 | /// Singleton implementation of which reads the current system time. 12 | /// It is recommended that for anything other than throwaway code, this is only referenced 13 | /// in a single place in your code: where you provide a value to inject into the rest of 14 | /// your application, which should only depend on the interface. 15 | /// 16 | /// This type has no state, and is thread-safe. See the thread safety section of the user guide for more information. 17 | [Immutable] 18 | public sealed class SystemClock : IClock 19 | { 20 | /// 21 | /// The singleton instance of . 22 | /// 23 | /// The singleton instance of . 24 | public static SystemClock Instance { get; } = new SystemClock(); 25 | 26 | /// 27 | /// Constructor present to prevent external construction. 28 | /// 29 | private SystemClock() 30 | { 31 | } 32 | 33 | /// 34 | /// Gets the current time as an . 35 | /// 36 | /// The current time in ticks as an . 37 | public Instant GetCurrentInstant() => NodaConstants.BclEpoch.PlusTicks(DateTime.UtcNow.Ticks); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/NodaTime/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using System.Resources; 7 | using System.Runtime.CompilerServices; 8 | 9 | [assembly: CLSCompliant(true)] 10 | [assembly: NeutralResourcesLanguage("en")] 11 | 12 | [assembly: InternalsVisibleTo("NodaTime.Benchmarks" + NodaTime.Properties.AssemblyInfo.PublicKeySuffix)] 13 | [assembly: InternalsVisibleTo("NodaTime.Test" + NodaTime.Properties.AssemblyInfo.PublicKeySuffix)] 14 | [assembly: InternalsVisibleTo("NodaTime.NzdPrinter" + NodaTime.Properties.AssemblyInfo.PublicKeySuffix)] 15 | [assembly: InternalsVisibleTo("NodaTime.TzdbCompiler" + NodaTime.Properties.AssemblyInfo.PublicKeySuffix)] 16 | [assembly: InternalsVisibleTo("NodaTime.TzdbCompiler.Test" + NodaTime.Properties.AssemblyInfo.PublicKeySuffix)] 17 | [assembly: InternalsVisibleTo("NodaTime.Benchmarks" + NodaTime.Properties.AssemblyInfo.PublicKeySuffix)] 18 | 19 | namespace NodaTime.Properties 20 | { 21 | /// 22 | /// Just a static class to house the public key, which allows us to avoid repeating it all over the place. 23 | /// 24 | internal static class AssemblyInfo 25 | { 26 | internal const string PublicKeySuffix = 27 | ",PublicKey=0024000004800000940000000602000000240000525341310004000001000100d335797ef2bff7" 28 | + "4db7c046f874523c553f88d3f8e0c2ba769820c54f0e64a11b47198b544c74abb487f8d3b64669" 29 | + "08ae2ac6fced4738e46a75e5661d5ac03fb29c7e26b13a220400cb9df95134e85716203f83b96f" 30 | + "ab661135c39b10f33e1c467a6750d8af331c602351b09a7bf5dd3a8943712d676481c5054c8031" 31 | + "84f77ed5"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/NodaTime/Extensions/DateTimeExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using System; 5 | 6 | namespace NodaTime.Extensions 7 | { 8 | /// 9 | /// Extension methods for . 10 | /// 11 | public static class DateTimeExtensions 12 | { 13 | /// 14 | /// Converts a of any kind to . 15 | /// 16 | /// This is a convenience method which calls . 17 | /// The DateTime to convert. 18 | /// A new with the same values as . 19 | public static LocalDateTime ToLocalDateTime(this DateTime dateTime) => LocalDateTime.FromDateTime(dateTime); 20 | 21 | /// 22 | /// Converts a with a kind of into an . 23 | /// 24 | /// This is a convenience method which calls . 25 | /// The DateTime to convert. 26 | /// An value representing the same instant in time as . 27 | /// does not have a kind of Utc. 28 | public static Instant ToInstant(this DateTime dateTime) => Instant.FromDateTimeUtc(dateTime); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/NodaTime.Test/ExceptionConstructorTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Text; 6 | using NUnit.Framework; 7 | using System; 8 | 9 | namespace NodaTime.Test 10 | { 11 | /// 12 | /// Tests for exceptions - we don't typically call the serialization code anywhere else, for example. 13 | /// 14 | public class ExceptionConstructorTests 15 | { 16 | // We never actually use this constructor, but it's in the public API and it's harmless... 17 | [Test] 18 | public void InvalidPatternExceptionParameterlessConstructor() 19 | { 20 | var exception = new InvalidPatternException(); 21 | Assert.AreEqual(new FormatException().Message, exception.Message); 22 | } 23 | 24 | // We never actually use these constructors, but they're in the public API and we don't want to create 25 | // a breaking change. They're obsolete to discourage external use though, as we want an UnparsableValueException 26 | // to always have a value. 27 | [Test, Obsolete] 28 | public void UnparsableValueObsoleteConstructors() 29 | { 30 | var exceptions = new[] 31 | { 32 | new UnparsableValueException(), 33 | new UnparsableValueException("message"), 34 | new UnparsableValueException("message", new Exception()) 35 | }; 36 | 37 | foreach (var exception in exceptions) 38 | { 39 | Assert.IsEmpty(exception.Value); 40 | Assert.AreEqual(-1, exception.Index); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/NodaTime.Test/TimeZones/AlgiersTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.TimeZones; 6 | using NUnit.Framework; 7 | 8 | namespace NodaTime.Test.TimeZones 9 | { 10 | /// 11 | /// Algiers had DST until May 1st 1981, after which time it didn't have any - so 12 | /// we use that to test a time zone whose transitions run out. (When Algiers 13 | /// decided to stop using DST, it changed its standard offset to be what had previously 14 | /// been its DST offset, i.e. +1.) 15 | /// 16 | public class AlgiersTest 17 | { 18 | private static readonly DateTimeZone Algiers = DateTimeZoneProviders.Tzdb["Africa/Algiers"]; 19 | 20 | [Test] 21 | public void GetPeriod_BeforeLast() 22 | { 23 | Instant april1981 = Instant.FromUtc(1981, 4, 1, 0, 0); 24 | var actual = Algiers.GetZoneInterval(april1981); 25 | var expected = new ZoneInterval("WET", Instant.FromUnixTimeTicks(3418020000000000L), Instant.FromUnixTimeTicks(3575232000000000L), Offset.Zero, Offset.Zero); 26 | Assert.AreEqual(expected, actual); 27 | } 28 | 29 | [Test] 30 | public void GetPeriod_AfterLastTransition() 31 | { 32 | var may1981 = DateTimeZone.Utc.AtStrictly(new LocalDateTime(1981, 5, 1, 0, 0, 1)).ToInstant(); 33 | var actual = Algiers.GetZoneInterval(may1981); 34 | var expected = new ZoneInterval("CET", Instant.FromUnixTimeTicks(3575232000000000L), null, Offset.FromSeconds(NodaConstants.SecondsPerHour), Offset.Zero); 35 | Assert.AreEqual(expected, actual); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NodaTime.Test/ConsistencyTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.TimeZones.Cldr; 6 | using NUnit.Framework; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | 12 | namespace NodaTime.Test 13 | { 14 | /// 15 | /// Tests using reflection to check that types are consistent. 16 | /// 17 | public class ConsistencyTest 18 | { 19 | private static IEnumerable AllPublicTypes = typeof(LocalDate).Assembly 20 | .GetTypes() 21 | .Where(t => t.IsPublic) 22 | .ToList(); 23 | 24 | [Test] 25 | public void EqualityOperatorForEquatable() 26 | { 27 | var expectedExceptions = new[] { typeof(MapZone) }; 28 | 29 | var failures = AllPublicTypes 30 | .Where(t => typeof(IEquatable<>).MakeGenericType(t).IsAssignableFrom(t)) 31 | .Where(t => t.GetMethod("op_Equality") is null) 32 | .Except(expectedExceptions) 33 | .ToList(); 34 | Assert.IsEmpty(failures); 35 | } 36 | 37 | [Test] 38 | public void ComparisonOperatorForComparable() 39 | { 40 | var expectedExceptions = new Type[] { }; 41 | 42 | var failures = AllPublicTypes 43 | .Where(t => typeof(IComparable<>).MakeGenericType(t).IsAssignableFrom(t)) 44 | .Where(t => t.GetMethod("op_LessThan") is null || t.GetMethod("op_LessThanOrEqual") is null) 45 | .Except(expectedExceptions) 46 | .ToList(); 47 | Assert.IsEmpty(failures); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/NodaTime/TimeAdjusters.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | 7 | namespace NodaTime 8 | { 9 | /// 10 | /// Factory class for time adjusters: functions from to LocalTime, 11 | /// which can be applied to , , and . 12 | /// 13 | public static class TimeAdjusters 14 | { 15 | /// 16 | /// Gets a time adjuster to truncate the time to the second, discarding fractional seconds. 17 | /// 18 | /// A time adjuster to truncate the time to the second, discarding fractional seconds. 19 | public static Func TruncateToSecond { get; } 20 | = time => new LocalTime(time.Hour, time.Minute, time.Second); 21 | 22 | /// 23 | /// Gets a time adjuster to truncate the time to the minute, discarding fractional minutes. 24 | /// 25 | /// A time adjuster to truncate the time to the minute, discarding fractional minutes. 26 | public static Func TruncateToMinute { get; } 27 | = time => new LocalTime(time.Hour, time.Minute); 28 | 29 | /// 30 | /// Get a time adjuster to truncate the time to the hour, discarding fractional hours. 31 | /// 32 | /// A time adjuster to truncate the time to the hour, discarding fractional hours. 33 | public static Func TruncateToHour { get; } 34 | = time => new LocalTime(time.Hour, 0); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/OffsetDateBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using NodaTime.Calendars; 7 | 8 | namespace NodaTime.Benchmarks.NodaTimeTests 9 | { 10 | public class OffsetDateBenchmarks 11 | { 12 | private static readonly Offset OneHourOffset = Offset.FromHours(1); 13 | private static readonly Offset LargePositiveOffset = Offset.FromHours(12); 14 | private static readonly LocalDate SampleLocal = new LocalDate(2009, 12, 26); 15 | private static readonly OffsetDate SampleEarlier = new OffsetDate(SampleLocal, -OneHourOffset); 16 | private static readonly OffsetDate Sample = new OffsetDate(SampleLocal, Offset.Zero); 17 | 18 | [Benchmark] 19 | public OffsetDate Construction() => new OffsetDate(SampleLocal, OneHourOffset); 20 | 21 | [Benchmark] 22 | public int Year() => Sample.Year; 23 | 24 | [Benchmark] 25 | public int Month() => Sample.Month; 26 | 27 | [Benchmark] 28 | public int DayOfMonth() => Sample.Day; 29 | 30 | [Benchmark] 31 | public IsoDayOfWeek DayOfWeek() => Sample.DayOfWeek; 32 | 33 | [Benchmark] 34 | public int DayOfYear() => Sample.DayOfYear; 35 | 36 | [Benchmark] 37 | public LocalDate Date() => Sample.Date; 38 | 39 | [Benchmark] 40 | public Era Era() => Sample.Era; 41 | 42 | [Benchmark] 43 | public int YearOfEra() => Sample.YearOfEra; 44 | 45 | // This just about stays within the same local day 46 | [Benchmark] 47 | public OffsetDate WithOffset() => SampleEarlier.WithOffset(LargePositiveOffset); 48 | } 49 | } -------------------------------------------------------------------------------- /src/NodaTime.Demo/TimeZoneDemo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.TimeZones; 6 | using NUnit.Framework; 7 | using System.Globalization; 8 | 9 | namespace NodaTime.Demo 10 | { 11 | public class TimeZoneDemo 12 | { 13 | [Test] 14 | public void EarlyParis() 15 | { 16 | // Yes, in 1900 Paris did (according to TZDB) have a UTC offset of 9 minutes, 21 seconds. 17 | DateTimeZone paris = DateTimeZoneProviders.Tzdb["Europe/Paris"]; 18 | Offset offset = Snippet.For(paris.GetUtcOffset(Instant.FromUtc(1900, 1, 1, 0, 0))); 19 | Assert.AreEqual("+00:09:21", offset.ToString("G", CultureInfo.InvariantCulture)); 20 | } 21 | 22 | [Test] 23 | public void BritishDoubleSummerTime() 24 | { 25 | DateTimeZone london = DateTimeZoneProviders.Tzdb["Europe/London"]; 26 | Offset offset = london.GetUtcOffset(Instant.FromUtc(1942, 7, 1, 0, 0)); 27 | Assert.AreEqual("+02", offset.ToString()); 28 | } 29 | 30 | [Test] 31 | public void ZoneInterval() 32 | { 33 | DateTimeZone london = DateTimeZoneProviders.Tzdb["Europe/London"]; 34 | ZoneInterval interval = Snippet.For(london.GetZoneInterval(Instant.FromUtc(2010, 6, 19, 0, 0))); 35 | Assert.AreEqual("BST", interval.Name); 36 | Assert.AreEqual(Instant.FromUtc(2010, 3, 28, 1, 0), interval.Start); 37 | Assert.AreEqual(Instant.FromUtc(2010, 10, 31, 1, 0), interval.End); 38 | Assert.AreEqual(Offset.FromHours(1), interval.WallOffset); 39 | Assert.AreEqual(Offset.FromHours(1), interval.Savings); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/BclTests/DateTimeOffsetBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Globalization; 8 | using BenchmarkDotNet.Attributes; 9 | 10 | namespace NodaTime.Benchmarks.BclTests 11 | { 12 | [Category("BCL")] 13 | public class DateTimeOffsetBenchmarks 14 | { 15 | private static readonly DateTimeOffset sample = new DateTimeOffset(2009, 12, 26, 10, 8, 30, 234, TimeSpan.Zero); 16 | private static readonly DateTimeOffset earlier = new DateTimeOffset(2009, 12, 26, 10, 8, 30, 234, TimeSpan.FromHours(1)); 17 | private static readonly DateTimeOffset later = new DateTimeOffset(2009, 12, 26, 10, 8, 30, 234, TimeSpan.FromHours(-1)); 18 | 19 | private static readonly IComparer defaultComparer = Comparer.Default; 20 | 21 | [Benchmark] 22 | public void CompareTo() 23 | { 24 | sample.CompareTo(earlier); 25 | sample.CompareTo(sample); 26 | sample.CompareTo(later); 27 | } 28 | 29 | [Benchmark] 30 | public void Comparer_Compare() 31 | { 32 | defaultComparer.Compare(sample, earlier); 33 | defaultComparer.Compare(sample, sample); 34 | defaultComparer.Compare(sample, later); 35 | } 36 | 37 | #pragma warning disable 1718 38 | [Benchmark] 39 | public bool Comparison_Operators() => (sample < earlier) | (sample < sample) | (sample < later); 40 | 41 | [Benchmark] 42 | [Category("Text")] 43 | public string Format() => sample.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/NodaTime.TzValidate.NzdCompatibility/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using CommandLine; 6 | using NodaTime.TimeZones; 7 | using NodaTime.Tools.Common; 8 | using System; 9 | using System.IO; 10 | using System.Net.Http; 11 | using System.Threading.Tasks; 12 | 13 | namespace NodaTime.TzValidate.NzdCompatibility 14 | { 15 | /// 16 | /// Based on NodaTime.TzValidate.NodaDump, this checks that Noda Time 1.1 can read an 17 | /// NZD file and produce the same result as the most recent version. 18 | /// 19 | internal class Program 20 | { 21 | private static async Task Main(string[] args) 22 | { 23 | Options options = new Options(); 24 | ICommandLineParser parser = new CommandLineParser(new CommandLineParserSettings(Console.Error)); 25 | if (!parser.ParseArguments(args, options)) 26 | { 27 | return 1; 28 | } 29 | var data = await FileUtility.LoadFileOrUrlAsync(options.Source); 30 | TzdbDateTimeZoneSource source = TzdbDateTimeZoneSource.FromStream(new MemoryStream(data)); 31 | var dumper = new ZoneDumper(source, options); 32 | try 33 | { 34 | using (var writer = options.OutputFile is null ? Console.Out : File.CreateText(options.OutputFile)) 35 | { 36 | dumper.Dump(writer); 37 | } 38 | } 39 | catch (UserErrorException e) 40 | { 41 | Console.Error.WriteLine($"Error: {e.Message}"); 42 | return 1; 43 | } 44 | 45 | return 0; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/NodaTime/Calendars/JulianYearMonthDayCalculator.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | namespace NodaTime.Calendars 6 | { 7 | internal sealed class JulianYearMonthDayCalculator : GJYearMonthDayCalculator 8 | { 9 | private const int AverageDaysPer10JulianYears = 3653; // Ideally 365.25 per year 10 | 11 | internal JulianYearMonthDayCalculator() 12 | : base(-9997, 9998, AverageDaysPer10JulianYears, -719164) 13 | { 14 | } 15 | 16 | internal override bool IsLeapYear(int year) => (year & 3) == 0; 17 | 18 | protected override int CalculateStartOfYearDays(int year) 19 | { 20 | // Unix epoch is 1970-01-01 Gregorian which is 1969-12-19 Julian. 21 | // Calculate relative to the nearest leap year and account for the 22 | // difference later. 23 | 24 | int relativeYear = year - 1968; 25 | int leapYears; 26 | if (relativeYear <= 0) 27 | { 28 | // Add 3 before shifting right since /4 and >>2 behave differently 29 | // on negative numbers. 30 | leapYears = (relativeYear + 3) >> 2; 31 | } 32 | else 33 | { 34 | leapYears = relativeYear >> 2; 35 | // For post 1968 an adjustment is needed as jan1st is before leap day 36 | if (!IsLeapYear(year)) 37 | { 38 | leapYears++; 39 | } 40 | } 41 | 42 | // Accounts for the difference between January 1st 1968 and December 19th 1969. 43 | return (relativeYear * 365 + leapYears - (366 + 352)); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Calendars/HebrewEcclesiasticalCalculatorTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Calendars; 6 | using NUnit.Framework; 7 | 8 | namespace NodaTime.Test.Calendars 9 | { 10 | public class HebrewScripturalCalculatorTest 11 | { 12 | [Test] 13 | public void DaysInYear() 14 | { 15 | var bcl = BclCalendars.Hebrew; 16 | var minYear = bcl.GetYear(bcl.MinSupportedDateTime); 17 | var maxYear = bcl.GetYear(bcl.MaxSupportedDateTime); 18 | 19 | for (int year = minYear; year <= maxYear; year++) 20 | { 21 | Assert.AreEqual(bcl.GetDaysInYear(year), HebrewScripturalCalculator.DaysInYear(year)); 22 | } 23 | } 24 | 25 | [Test] 26 | public void DaysInMonth() 27 | { 28 | var bcl = BclCalendars.Hebrew; 29 | // Not all months in the min/max years are supported 30 | var minYear = bcl.GetYear(bcl.MinSupportedDateTime) + 1; 31 | var maxYear = bcl.GetYear(bcl.MaxSupportedDateTime) - 1; 32 | 33 | for (int year = minYear; year <= maxYear; year++) 34 | { 35 | int months = bcl.GetMonthsInYear(year); 36 | for (int month = 1; month <= months; month++) 37 | { 38 | int scripturalMonth = HebrewMonthConverter.CivilToScriptural(year, month); 39 | int bclDays = bcl.GetDaysInMonth(year, month); 40 | int nodaDays = HebrewScripturalCalculator.DaysInMonth(year, scripturalMonth); 41 | Assert.AreEqual(bclDays, nodaDays); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Xml/XmlSchemaTest.XmlSchemaExporter.approved.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Annotations/ReflectionTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using NodaTime.Annotations; 5 | using NUnit.Framework; 6 | using System; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Text.RegularExpressions; 10 | 11 | namespace NodaTime.Test.Annotations 12 | { 13 | /// 14 | /// Not necessarily annotations, but a general purpose "anything using reflection" test. 15 | /// 16 | public class ReflectionTest 17 | { 18 | [Test] 19 | public void ConversionNamesMatchTargetType() 20 | { 21 | Regex conversionName = new Regex("^To([A-Z][a-zA-Z0-9]*)$"); 22 | 23 | var badMethods = typeof(Instant).Assembly 24 | .DefinedTypes 25 | .Where(t => t.IsPublic || t.IsNestedPublic) 26 | .OrderBy(t => t.Name) 27 | .SelectMany(m => m.DeclaredMethods) 28 | .Where(m => m.IsPublic) 29 | .Where(m => conversionName.IsMatch(m.Name)) 30 | .Where(NameIsInconsistentWithReturnType); 31 | 32 | TestHelper.AssertNoFailures(badMethods, m => $"{m.DeclaringType?.Name}.{m.Name}", TestExemptionCategory.ConversionName); 33 | 34 | bool NameIsInconsistentWithReturnType(MethodInfo method) 35 | { 36 | var type = method.ReturnType; 37 | // When converting to an interface, the I prefix stutters somewhat - so we have "ToClock" instead of "ToIClock" for example. 38 | var expectedTypeName = type.IsInterface ? type.Name.Substring(1) : type.Name; 39 | return !method.Name.StartsWith($"To{expectedTypeName}", StringComparison.Ordinal); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Globalization/FailingCultureInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using System.Globalization; 7 | 8 | namespace NodaTime.Test.Globalization 9 | { 10 | /// 11 | /// Throws an exception if called. This forces the testing code to set or pass a valid culture in all 12 | /// tests. The tests cannot be guaranteed to work if the culture is not set as formatting and parsing 13 | /// are culture dependent. 14 | /// 15 | public class FailingCultureInfo : CultureInfo 16 | { 17 | private const string CultureNotSet = "The formatting and parsing code tests should have set the correct culture."; 18 | 19 | public static FailingCultureInfo Instance = new FailingCultureInfo(); 20 | 21 | public FailingCultureInfo() 22 | : base("en-US") 23 | { 24 | } 25 | 26 | public override DateTimeFormatInfo DateTimeFormat 27 | { 28 | get 29 | { 30 | throw new NotSupportedException(CultureNotSet); 31 | } 32 | set 33 | { 34 | throw new NotSupportedException(CultureNotSet); 35 | } 36 | } 37 | 38 | public override NumberFormatInfo NumberFormat 39 | { 40 | get 41 | { 42 | throw new NotSupportedException(CultureNotSet); 43 | } 44 | set 45 | { 46 | throw new NotSupportedException(CultureNotSet); 47 | } 48 | } 49 | 50 | public override string Name => "Failing"; 51 | 52 | public override object GetFormat(Type? formatType) => 53 | throw new NotSupportedException(CultureNotSet); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/NodaTime/TimeZones/DateTimeZoneNotFoundException.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Annotations; 6 | using System; 7 | 8 | // Standard exception constructors. 9 | // This exception is expected to be constructed within the library. 10 | // There are never any inner exceptions, and we always *do* have a message. 11 | #pragma warning disable CA1032 12 | 13 | namespace NodaTime.TimeZones 14 | { 15 | /// 16 | /// Exception thrown when time zone is requested from an , 17 | /// but the specified ID is invalid for that provider. 18 | /// 19 | /// 20 | /// This type originally existed as TimeZoneNotFoundException doesn't exist in framework versions 21 | /// targeted by earlier versions of Noda Time. It is present now solely to avoid unnecessary 22 | /// backward incompatibility. While it could be used to distinguish between exceptions thrown by 23 | /// Noda Time and those thrown by TimeZoneInfo, we recommend that you don't use it that way. 24 | /// 25 | /// Any public static members of this type are thread safe. Any instance members are not guaranteed to be thread safe. 26 | /// See the thread safety section of the user guide for more information. 27 | /// 28 | [Mutable] // Exception itself is mutable 29 | public sealed class DateTimeZoneNotFoundException : TimeZoneNotFoundException 30 | { 31 | /// 32 | /// Creates an instance with the given message. 33 | /// 34 | /// The message for the exception. 35 | public DateTimeZoneNotFoundException(string message) : base(message) { } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/NodaTime.Test/CalendarSystemTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using NUnit.Framework; 9 | 10 | namespace NodaTime.Test 11 | { 12 | public partial class CalendarSystemTest 13 | { 14 | private static readonly IEnumerable SupportedIds = CalendarSystem.Ids.ToList(); 15 | private static readonly List SupportedCalendars = SupportedIds.Select(CalendarSystem.ForId).ToList(); 16 | 17 | [Test] 18 | [TestCaseSource(nameof(SupportedCalendars))] 19 | public void MaxDate(CalendarSystem calendar) 20 | { 21 | // Construct the largest LocalDate we can, and validate that all the properties can be fetched without 22 | // issues. 23 | ValidateProperties(calendar, calendar.MaxDays, calendar.MaxYear); 24 | } 25 | 26 | [Test] 27 | [TestCaseSource(nameof(SupportedCalendars))] 28 | public void MinDate(CalendarSystem calendar) 29 | { 30 | // Construct the smallest LocalDate we can, and validate that all the properties can be fetched without 31 | // issues. 32 | ValidateProperties(calendar, calendar.MinDays, calendar.MinYear); 33 | } 34 | 35 | private static void ValidateProperties(CalendarSystem calendar, int daysSinceEpoch, int expectedYear) 36 | { 37 | var localDate = new LocalDate(daysSinceEpoch, calendar); 38 | Assert.AreEqual(expectedYear, localDate.Year); 39 | 40 | foreach (var property in typeof(LocalDate).GetTypeInfo().DeclaredProperties) 41 | { 42 | property.GetValue(localDate, null); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/NodaTime.Test/TypeInitializationTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | #if NET6_0_OR_GREATER 6 | using NUnit.Framework; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Reflection; 11 | using System.Runtime.CompilerServices; 12 | using System.Runtime.Loader; 13 | 14 | namespace NodaTime.Test; 15 | 16 | public class TypeInitializationTest 17 | { 18 | private static IEnumerable TypesToTest => typeof(Instant).Assembly.GetTypes() 19 | .Where(t => !t.IsGenericTypeDefinition) 20 | .Where(t => !t.IsEnum) 21 | .Where(t => t.BaseType != typeof(MulticastDelegate)); 22 | 23 | [Test] 24 | [TestCaseSource(nameof(TypesToTest))] 25 | public void InitializeType(Type type) 26 | { 27 | var typeInContext = LoadTypeInContext(type); 28 | RuntimeHelpers.RunClassConstructor(typeInContext.TypeHandle); 29 | } 30 | 31 | [Test] 32 | [TestCaseSource(nameof(TypesToTest))] 33 | public void GetProperties(Type type) 34 | { 35 | var typeInContext = LoadTypeInContext(type); 36 | RuntimeHelpers.RunClassConstructor(typeInContext.TypeHandle); 37 | 38 | foreach (var property in typeInContext.GetProperties(BindingFlags.Static | BindingFlags.Public).Where(p => p.CanRead)) 39 | { 40 | property.GetValue(null); 41 | } 42 | } 43 | 44 | private static Type LoadTypeInContext(Type type) 45 | { 46 | var location = type.Assembly.Location; 47 | var context = new AssemblyLoadContext($"Context for {type.FullName}"); 48 | var contextAssembly = context.LoadFromAssemblyPath(location); 49 | return contextAssembly.GetType(type.FullName!) ?? throw new Exception($"Couldn't load type {type}"); 50 | } 51 | } 52 | #endif 53 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/OffsetTimeBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | 7 | namespace NodaTime.Benchmarks.NodaTimeTests 8 | { 9 | public class OffsetTimeBenchmarks 10 | { 11 | private static readonly Offset OneHourOffset = Offset.FromHours(1); 12 | private static readonly Offset LargePositiveOffset = Offset.FromHours(12); 13 | private static readonly LocalTime SampleLocal = new LocalTime(11, 23, 45, 56); 14 | private static readonly OffsetTime SampleEarlier = new OffsetTime(SampleLocal, -OneHourOffset); 15 | private static readonly OffsetTime Sample = new OffsetTime(SampleLocal, Offset.Zero); 16 | 17 | [Benchmark] 18 | public OffsetTime Construction() => new OffsetTime(SampleLocal, OneHourOffset); 19 | 20 | [Benchmark] 21 | public int Hour() => Sample.Hour; 22 | 23 | [Benchmark] 24 | public int Minute() => Sample.Minute; 25 | 26 | [Benchmark] 27 | public int Second() => Sample.Second; 28 | 29 | [Benchmark] 30 | public int NanosecondOfSecond() => Sample.NanosecondOfSecond; 31 | 32 | [Benchmark] 33 | public long NanosecondOfDay() => Sample.NanosecondOfDay; 34 | 35 | [Benchmark] 36 | public int Millisecond() => Sample.Millisecond; 37 | 38 | [Benchmark] 39 | public int TickOfSecond() => Sample.TickOfSecond; 40 | 41 | [Benchmark] 42 | public long TickOfDay() => Sample.TickOfDay; 43 | 44 | [Benchmark] 45 | public LocalTime TimeOfDay() => Sample.TimeOfDay; 46 | 47 | // This just about stays within the same local day 48 | [Benchmark] 49 | public OffsetTime WithOffset() => SampleEarlier.WithOffset(LargePositiveOffset); 50 | } 51 | } -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/DateIntervalBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | 6 | using BenchmarkDotNet.Attributes; 7 | 8 | namespace NodaTime.Benchmarks.NodaTimeTests 9 | { 10 | public class DateIntervalBenchmarks 11 | { 12 | private static readonly DateInterval JanuaryJune2017 = new DateInterval(new LocalDate(2017, 1, 1), new LocalDate(2017, 6, 30)); 13 | private static readonly DateInterval MarchSeptember2017 = new DateInterval(new LocalDate(2017, 3, 1), new LocalDate(2017, 9, 30)); 14 | private static readonly DateInterval AugustDecember2017 = new DateInterval(new LocalDate(2017, 8, 1), new LocalDate(2017, 12, 31)); 15 | private static readonly DateInterval FebruaryMarch2017 = new DateInterval(new LocalDate(2017, 2, 1), new LocalDate(2017, 3, 31)); 16 | 17 | [Benchmark] 18 | public int Length() => JanuaryJune2017.Length; 19 | 20 | [Benchmark] 21 | public DateInterval? Union_Disjoint() => JanuaryJune2017.Union(AugustDecember2017); 22 | 23 | [Benchmark] 24 | public DateInterval? Union_Overlapping() => JanuaryJune2017.Union(MarchSeptember2017); 25 | 26 | [Benchmark] 27 | public DateInterval? Intersection_Disjoint() => JanuaryJune2017.Intersection(AugustDecember2017); 28 | 29 | [Benchmark] 30 | public DateInterval? Intersection_Overlapping() => JanuaryJune2017.Intersection(MarchSeptember2017); 31 | 32 | [Benchmark] 33 | public bool Contains_Disjoint() => JanuaryJune2017.Contains(AugustDecember2017); 34 | 35 | [Benchmark] 36 | public bool Contains_Overlapping() => JanuaryJune2017.Contains(MarchSeptember2017); 37 | 38 | [Benchmark] 39 | public bool Contains_Contained() => JanuaryJune2017.Contains(FebruaryMarch2017); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/NodaTime.Test/TimeZones/TimeZoneInfoReplacer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.TimeZones; 6 | using System; 7 | using System.Collections.ObjectModel; 8 | using System.Linq; 9 | 10 | namespace NodaTime.Test.TimeZones 11 | { 12 | /// 13 | /// Class used to temporarily replace the shim used by , 14 | /// for test purposes. On disposal, the original is restored. 15 | /// 16 | internal class TimeZoneInfoReplacer : IDisposable, TimeZoneInfoInterceptor.ITimeZoneInfoShim 17 | { 18 | private readonly TimeZoneInfoInterceptor.ITimeZoneInfoShim originalShim; 19 | private readonly ReadOnlyCollection zones; 20 | 21 | public TimeZoneInfo? Local { get; } 22 | 23 | private TimeZoneInfoReplacer(TimeZoneInfo? local, ReadOnlyCollection zones) 24 | { 25 | originalShim = TimeZoneInfoInterceptor.Shim; 26 | Local = local; 27 | this.zones = zones; 28 | TimeZoneInfoInterceptor.Shim = this; 29 | 30 | } 31 | 32 | internal static IDisposable Replace(TimeZoneInfo? local, params TimeZoneInfo[] allZones) => 33 | new TimeZoneInfoReplacer(local, allZones.ToList().AsReadOnly()); 34 | 35 | public TimeZoneInfo FindSystemTimeZoneById(string id) 36 | { 37 | var zone = zones.FirstOrDefault(z => z.Id == id); 38 | if (zone != null) 39 | { 40 | return zone; 41 | } 42 | throw new TimeZoneNotFoundException($"No such time zone: {id}"); 43 | } 44 | 45 | public ReadOnlyCollection GetSystemTimeZones() => zones; 46 | 47 | public void Dispose() => TimeZoneInfoInterceptor.Shim = originalShim; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/UtcZonedDateTimeBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using NodaTime.Calendars; 7 | 8 | namespace NodaTime.Benchmarks.NodaTimeTests 9 | { 10 | public class UtcZonedDateTimeBenchmarks 11 | { 12 | private static readonly LocalDateTime SampleLocal = new LocalDateTime(2009, 12, 26, 10, 8, 30); 13 | private static readonly ZonedDateTime Sample = DateTimeZone.Utc.AtStrictly(SampleLocal); 14 | 15 | [Benchmark] 16 | public void Construction() 17 | { 18 | DateTimeZone.Utc.AtStrictly(SampleLocal); 19 | } 20 | 21 | [Benchmark] 22 | public int Year() => Sample.Year; 23 | 24 | [Benchmark] 25 | public int Month() => Sample.Month; 26 | 27 | [Benchmark] 28 | public int DayOfMonth() => Sample.Day; 29 | 30 | [Benchmark] 31 | public IsoDayOfWeek DayOfWeek() => Sample.DayOfWeek; 32 | 33 | [Benchmark] 34 | public int DayOfYear() => Sample.DayOfYear; 35 | 36 | [Benchmark] 37 | public int Hour() => Sample.Hour; 38 | 39 | [Benchmark] 40 | public int Minute() => Sample.Minute; 41 | 42 | [Benchmark] 43 | public int Second() => Sample.Second; 44 | 45 | [Benchmark] 46 | public int Millisecond() => Sample.Millisecond; 47 | 48 | [Benchmark] 49 | public long TickOfDay() => Sample.TickOfDay; 50 | 51 | [Benchmark] 52 | public int TickOfSecond() => Sample.TickOfSecond; 53 | 54 | [Benchmark] 55 | public int ClockHourOfHalfDay() => Sample.ClockHourOfHalfDay; 56 | 57 | [Benchmark] 58 | public Era Era() => Sample.Era; 59 | 60 | [Benchmark] 61 | public int YearOfEra() => Sample.YearOfEra; 62 | } 63 | } -------------------------------------------------------------------------------- /src/NodaTime.Demo/AnnualDateDemo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | using System; 7 | namespace NodaTime.Demo 8 | { 9 | class AnnualDateDemo 10 | { 11 | [Test] 12 | public void CompareTo() 13 | { 14 | var february23rd = new AnnualDate(2, 23); 15 | var august17th = new AnnualDate(8, 17); 16 | 17 | var lessThan = Snippet.For(february23rd.CompareTo(august17th)); 18 | var equal = february23rd.CompareTo(february23rd); 19 | var greaterThan = august17th.CompareTo(february23rd); 20 | 21 | Assert.Less(lessThan, 0); 22 | Assert.AreEqual(0, equal); 23 | Assert.Greater(greaterThan, 0); 24 | } 25 | 26 | [Test] 27 | public void Equals() 28 | { 29 | var february23rd = new AnnualDate(2, 23); 30 | var august17th = new AnnualDate(8, 17); 31 | 32 | var unequal = Snippet.For(february23rd.Equals(august17th)); 33 | var equal = february23rd.Equals(february23rd); 34 | 35 | Assert.False(unequal); 36 | Assert.True(equal); 37 | } 38 | 39 | [Test] 40 | public void InYear() 41 | { 42 | var annualDate = new AnnualDate(3, 12); 43 | var localDate = Snippet.For(annualDate.InYear(2013)); 44 | 45 | Assert.AreEqual(new LocalDate(2013, 3, 12), localDate); 46 | } 47 | 48 | [Test] 49 | public void IsValidYear() 50 | { 51 | var leapDay = new AnnualDate(2, 29); 52 | 53 | var leapYear = Snippet.For(leapDay.IsValidYear(2020)); 54 | var nonLeapYear = leapDay.IsValidYear(2018); 55 | 56 | Assert.True(leapYear); 57 | Assert.False(nonLeapYear); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/NodaTime.Demo/InstantDemo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NUnit.Framework; 6 | 7 | namespace NodaTime.Demo 8 | { 9 | public class InstantDemo 10 | { 11 | [Test] 12 | public void Construction() 13 | { 14 | // 10 million ticks = 1 second... 15 | Instant instant = Instant.FromUnixTimeTicks(10000000); 16 | // Epoch is 1970 UTC 17 | // An instant isn't really "in" a time zone or calendar, but 18 | // it's convenient to consider UTC in the ISO-8601 calendar. 19 | Assert.AreEqual("1970-01-01T00:00:01Z", instant.ToString()); 20 | } 21 | 22 | [Test] 23 | public void AdditionWithDuration() 24 | { 25 | // Some arbitrary instant. I've no idea when. 26 | Instant instant = Instant.FromUnixTimeTicks(150000000); 27 | // A very short duration: a duration is simply a number of ticks. 28 | Duration duration = Duration.FromTicks(1000); 29 | Instant later = instant + duration; 30 | Assert.AreEqual(Instant.FromUnixTimeTicks(150001000), later); 31 | } 32 | 33 | [Test] 34 | public void Comparison() 35 | { 36 | Instant early = Instant.FromUnixTimeTicks(1000); 37 | Instant late = Instant.FromUnixTimeTicks(2000); 38 | Assert.That(early < late); 39 | } 40 | 41 | [Test] 42 | public void ConvenienceConstruction() 43 | { 44 | Instant instant = Instant.FromUtc(2010, 6, 9, 14, 15, 0); 45 | // Here's a number I prepared earlier... 46 | Assert.AreEqual(12760929000000000, instant.ToUnixTimeTicks()); 47 | // But it really is correct 48 | Assert.AreEqual("2010-06-09T14:15:00Z", instant.ToString()); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/NodaTime.Test/Calendars/IsoCalendarSystemTest.Era.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Calendars; 6 | using NUnit.Framework; 7 | 8 | namespace NodaTime.Test.Calendars 9 | { 10 | public partial class IsoCalendarSystemTest 11 | { 12 | [Test] 13 | public void GetMaxYearOfEra() 14 | { 15 | LocalDate date = new LocalDate(Iso.MaxYear, 1, 1); 16 | Assert.AreEqual(date.YearOfEra, Iso.GetMaxYearOfEra(Era.Common)); 17 | Assert.AreEqual(Era.Common, date.Era); 18 | date = new LocalDate(Iso.MinYear, 1, 1); 19 | Assert.AreEqual(Iso.MinYear, date.Year); 20 | Assert.AreEqual(date.YearOfEra, Iso.GetMaxYearOfEra(Era.BeforeCommon)); 21 | Assert.AreEqual(Era.BeforeCommon, date.Era); 22 | } 23 | 24 | [Test] 25 | public void GetMinYearOfEra() 26 | { 27 | LocalDate date = new LocalDate(1, 1, 1); 28 | Assert.AreEqual(date.YearOfEra, Iso.GetMinYearOfEra(Era.Common)); 29 | Assert.AreEqual(Era.Common, date.Era); 30 | date = new LocalDate(0, 1, 1); 31 | Assert.AreEqual(date.YearOfEra, Iso.GetMinYearOfEra(Era.BeforeCommon)); 32 | Assert.AreEqual(Era.BeforeCommon, date.Era); 33 | } 34 | 35 | [Test] 36 | public void GetAbsoluteYear() 37 | { 38 | Assert.AreEqual(1, Iso.GetAbsoluteYear(1, Era.Common)); 39 | Assert.AreEqual(0, Iso.GetAbsoluteYear(1, Era.BeforeCommon)); 40 | Assert.AreEqual(-1, Iso.GetAbsoluteYear(2, Era.BeforeCommon)); 41 | Assert.AreEqual(Iso.MaxYear, Iso.GetAbsoluteYear(Iso.GetMaxYearOfEra(Era.Common), Era.Common)); 42 | Assert.AreEqual(Iso.MinYear, Iso.GetAbsoluteYear(Iso.GetMaxYearOfEra(Era.BeforeCommon), Era.BeforeCommon)); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/NodaTime/NodaTime.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Noda Time is a date and time API acting as an alternative to the built-in DateTime/DateTimeOffset etc types in .NET. 4 | Noda Time 5 | Jon Skeet 6 | netstandard2.0;net6.0;net8.0 7 | true 8 | CA1303 9 | True 10 | true 11 | true 12 | date;time;timezone;calendar;nodatime 13 | README.md 14 | true 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | lib/native/ 25 | true 26 | 27 | 28 | build/native/ 29 | true 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | all 42 | runtime; build; native; contentfiles; analyzers 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Annotations/TrustedTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using NodaTime.Annotations; 8 | using NUnit.Framework; 9 | 10 | #if NET6_0_OR_GREATER 11 | namespace NodaTime.Test.Annotations 12 | { 13 | public class TrustedTest 14 | { 15 | [Test] 16 | public void MembersWithTrustedParametersAreNotPublic() 17 | { 18 | var types = typeof(Instant).Assembly.DefinedTypes; 19 | var invalidMembers = types.SelectMany(t => t.DeclaredMembers) 20 | .Where(m => GetParameters(m).Any(p => p.IsDefined(typeof(TrustedAttribute), false))) 21 | .Where(InvalidForTrustedParameters); 22 | 23 | TestHelper.AssertNoFailures(invalidMembers, FormatMemberDebugName); 24 | } 25 | 26 | private static string FormatMemberDebugName(MemberInfo m) => 27 | string.Format("{0}.{1}({2})", 28 | m.DeclaringType?.Name, 29 | m.Name, 30 | string.Join(", ", GetParameters(m).Select(p => p.ParameterType))); 31 | 32 | private static bool InvalidForTrustedParameters(dynamic member) => 33 | // We'll need to be more specific at some point, but this will do to start with... 34 | member.IsPublic && (member.DeclaringType.IsPublic || member.DeclaringType.IsNestedPublic); 35 | 36 | private static IEnumerable GetParameters(MemberInfo member) 37 | { 38 | switch (member) 39 | { 40 | case MethodBase method: return method.GetParameters(); 41 | case PropertyInfo property: return property.GetIndexParameters(); 42 | default: return Enumerable.Empty(); 43 | } 44 | } 45 | } 46 | } 47 | #endif 48 | -------------------------------------------------------------------------------- /src/NodaTime.Test/ZonedClockTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Extensions; 6 | using NodaTime.Testing; 7 | using NodaTime.Testing.TimeZones; 8 | using NUnit.Framework; 9 | 10 | namespace NodaTime.Test 11 | { 12 | public class ZonedClockTest 13 | { 14 | private static readonly DateTimeZone SampleZone = new SingleTransitionDateTimeZone(NodaConstants.UnixEpoch, 1, 2); 15 | 16 | [Test] 17 | public void GetCurrent() 18 | { 19 | var julian = CalendarSystem.Julian; 20 | FakeClock underlyingClock = new FakeClock(NodaConstants.UnixEpoch); 21 | ZonedClock zonedClock = underlyingClock.InZone(SampleZone, julian); 22 | Assert.AreEqual(NodaConstants.UnixEpoch, zonedClock.GetCurrentInstant()); 23 | Assert.AreEqual(new ZonedDateTime(underlyingClock.GetCurrentInstant(), SampleZone, julian), 24 | zonedClock.GetCurrentZonedDateTime()); 25 | Assert.AreEqual(new LocalDateTime(1969, 12, 19, 2, 0, julian), zonedClock.GetCurrentLocalDateTime()); 26 | Assert.AreEqual(new LocalDateTime(1969, 12, 19, 2, 0, julian).WithOffset(Offset.FromHours(2)), 27 | zonedClock.GetCurrentOffsetDateTime()); 28 | Assert.AreEqual(new LocalDate(1969, 12, 19, julian), zonedClock.GetCurrentDate()); 29 | Assert.AreEqual(new LocalTime(2, 0, 0), zonedClock.GetCurrentTimeOfDay()); 30 | } 31 | 32 | [Test] 33 | public void Properties() 34 | { 35 | var calendar = CalendarSystem.Julian; 36 | var clock = new FakeClock(NodaConstants.UnixEpoch); 37 | var zonedClock = clock.InZone(SampleZone, calendar); 38 | Assert.AreSame(clock, zonedClock.Clock); 39 | Assert.AreSame(calendar, zonedClock.Calendar); 40 | Assert.AreSame(SampleZone, zonedClock.Zone); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/StandardDaylightAlternatingMapBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using NodaTime.TimeZones; 7 | 8 | #if !NO_INTERNALS 9 | namespace NodaTime.Benchmarks.NodaTimeTests 10 | { 11 | /// 12 | /// Benchmarks for operations on an uncached StandardDaylightAlternatingMap. 13 | /// 14 | public class StandardDaylightAlternatingMapBenchmarks 15 | { 16 | private static readonly Instant February1st = Instant.FromUtc(2010, 2, 1, 0, 0); 17 | private static readonly Instant July1st = Instant.FromUtc(2010, 7, 1, 0, 0); 18 | 19 | private static readonly StandardDaylightAlternatingMap SampleZone; 20 | 21 | static StandardDaylightAlternatingMapBenchmarks() 22 | { 23 | // Build a daylight savings zone which basically models modern America/Los_Angeles. 24 | SampleZone = new StandardDaylightAlternatingMap(Offset.FromHours(-8), 25 | new ZoneRecurrence("PDT", Offset.FromHours(1), 26 | new ZoneYearOffset(TransitionMode.Wall, monthOfYear: 3, dayOfMonth: 8, dayOfWeek: 7, 27 | advance: true, timeOfDay: new LocalTime(2, 0)), 28 | int.MinValue, int.MaxValue), 29 | new ZoneRecurrence("PST", Offset.FromHours(0), 30 | new ZoneYearOffset(TransitionMode.Standard, monthOfYear: 11, dayOfMonth: 1, dayOfWeek: 7, 31 | advance: true, timeOfDay: new LocalTime(2, 0)), 32 | int.MinValue, int.MaxValue)); 33 | } 34 | 35 | [Benchmark] 36 | public ZoneInterval GetZoneInterval_Winter() => SampleZone.GetZoneInterval(February1st); 37 | 38 | [Benchmark] 39 | public ZoneInterval GetZoneInterval_Summer() => SampleZone.GetZoneInterval(July1st); 40 | } 41 | } 42 | #endif 43 | -------------------------------------------------------------------------------- /src/NodaTime/Calendars/SingleEraCalculator.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Utility; 6 | 7 | namespace NodaTime.Calendars 8 | { 9 | /// 10 | /// Implementation of for calendars which only have a single era. 11 | /// 12 | internal sealed class SingleEraCalculator : EraCalculator 13 | { 14 | private readonly Era era; 15 | 16 | private readonly int minYear; 17 | private readonly int maxYear; 18 | 19 | internal SingleEraCalculator(Era era, YearMonthDayCalculator ymdCalculator) : base(era) 20 | { 21 | minYear = ymdCalculator.MinYear; 22 | maxYear = ymdCalculator.MaxYear; 23 | this.era = era; 24 | } 25 | 26 | private void ValidateEra(Era era) 27 | { 28 | if (era != this.era) 29 | { 30 | Preconditions.CheckNotNull(era, nameof(era)); 31 | Preconditions.CheckArgument(era == this.era, nameof(era), "Only supported era is {0}; requested era was {1}", 32 | this.era.Name, era.Name); 33 | } 34 | } 35 | 36 | internal override int GetAbsoluteYear(int yearOfEra, Era era) 37 | { 38 | ValidateEra(era); 39 | Preconditions.CheckArgumentRange(nameof(yearOfEra), yearOfEra, minYear, maxYear); 40 | return yearOfEra; 41 | } 42 | 43 | internal override int GetYearOfEra(int absoluteYear) => absoluteYear; 44 | 45 | internal override int GetMinYearOfEra(Era era) 46 | { 47 | ValidateEra(era); 48 | return minYear; 49 | } 50 | 51 | internal override int GetMaxYearOfEra(Era era) 52 | { 53 | ValidateEra(era); 54 | return maxYear; 55 | } 56 | 57 | internal override Era GetEra(int absoluteYear) => era; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/NodaTime.Test/Utility/BclConversionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using System; 6 | using NodaTime.Utility; 7 | using NUnit.Framework; 8 | using NodaTime.Extensions; 9 | 10 | namespace NodaTime.Test.Utility 11 | { 12 | public class BclConversionsTest 13 | { 14 | // This tests both directions for all valid values. 15 | // Alternatively, we could have checked names... 16 | // it doesn't matter much. 17 | [TestCase(DayOfWeek.Sunday, IsoDayOfWeek.Sunday)] 18 | [TestCase(DayOfWeek.Monday, IsoDayOfWeek.Monday)] 19 | [TestCase(DayOfWeek.Tuesday, IsoDayOfWeek.Tuesday)] 20 | [TestCase(DayOfWeek.Wednesday, IsoDayOfWeek.Wednesday)] 21 | [TestCase(DayOfWeek.Thursday, IsoDayOfWeek.Thursday)] 22 | [TestCase(DayOfWeek.Friday, IsoDayOfWeek.Friday)] 23 | [TestCase(DayOfWeek.Saturday, IsoDayOfWeek.Saturday)] 24 | public void DayOfWeek_BothWaysValid(DayOfWeek bcl, IsoDayOfWeek noda) 25 | { 26 | Assert.AreEqual(bcl, BclConversions.ToDayOfWeek(noda)); 27 | Assert.AreEqual(noda, BclConversions.ToIsoDayOfWeek(bcl)); 28 | Assert.AreEqual(bcl, noda.ToDayOfWeek()); 29 | Assert.AreEqual(noda, bcl.ToIsoDayOfWeek()); 30 | } 31 | 32 | [TestCase(0)] 33 | [TestCase(8)] 34 | public void ToDayOfWeek_InvalidValues(IsoDayOfWeek noda) 35 | { 36 | Assert.Throws(() => BclConversions.ToDayOfWeek(noda)); 37 | Assert.Throws(() => noda.ToDayOfWeek()); 38 | } 39 | 40 | [TestCase(-1)] 41 | [TestCase(7)] 42 | public void ToIsoDayOfWeek_InvalidValues(DayOfWeek bcl) 43 | { 44 | Assert.Throws(() => BclConversions.ToIsoDayOfWeek(bcl)); 45 | Assert.Throws(() => bcl.ToIsoDayOfWeek()); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/NodaTime/Xml/XmlSerializationSettings.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using NodaTime.Utility; 6 | 7 | namespace NodaTime.Xml 8 | { 9 | /// 10 | /// Ambient settings applied during XML serialization and deserialization. 11 | /// XML serialization in .NET does not provide any "hooks" for advanced configuration. 12 | /// Most of the time that's a good thing, in terms of compatibility: we want 13 | /// the same data to be serialized the same way across multiple programs for 14 | /// interoperability. There are some exceptions to this however, where decisions 15 | /// need to be made and there's no single "right for everyone" choice. 16 | /// 17 | public static class XmlSerializationSettings 18 | { 19 | private static readonly object stateLock = new object(); 20 | 21 | private static IDateTimeZoneProvider dateTimeZoneProvider = DateTimeZoneProviders.Tzdb; 22 | 23 | /// 24 | /// Gets the to use to interpret a time zone ID read as part of 25 | /// XML serialization. 26 | /// 27 | /// 28 | /// This property defaults to . 29 | /// 30 | /// The IDateTimeZoneProvider to use to interpret a time zone ID read as part of 31 | /// XML serialization. 32 | public static IDateTimeZoneProvider DateTimeZoneProvider 33 | { 34 | get 35 | { 36 | lock (stateLock) 37 | { 38 | return dateTimeZoneProvider; 39 | } 40 | } 41 | set 42 | { 43 | lock (stateLock) 44 | { 45 | dateTimeZoneProvider = Preconditions.CheckNotNull(value, nameof(value)); 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/NodaTime.Benchmarks/NodaTimeTests/Calendars/IsoCalendarBenchmarks.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Noda Time Authors. All rights reserved. 2 | // Use of this source code is governed by the Apache License 2.0, 3 | // as found in the LICENSE.txt file. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using NodaTime.Calendars; 7 | 8 | namespace NodaTime.Benchmarks.NodaTimeTests.Calendars 9 | { 10 | public class IsoCalendarBenchmarks 11 | { 12 | #if !V1 13 | private static readonly YearMonthDayCalculator IsoCalculator = CalendarSystem.Iso.YearMonthDayCalculator; 14 | private static readonly YearMonthDay SampleOptimizedYearMonthDay = new YearMonthDay(2014, 6, 28); 15 | private static readonly YearMonthDay SampleNotOptimizedYearMonthDay = new YearMonthDay(1600, 6, 28); 16 | #endif 17 | 18 | [Benchmark] 19 | public void GetDaysInMonth_NotFebruary() 20 | { 21 | CalendarSystem.Iso.GetDaysInMonth(2012, 1); 22 | } 23 | 24 | [Benchmark] 25 | public void GetDaysInMonth_FebruaryNonLeap() 26 | { 27 | CalendarSystem.Iso.GetDaysInMonth(2011, 2); 28 | } 29 | 30 | [Benchmark] 31 | public void GetDaysInMonth_FebruaryLeap() 32 | { 33 | CalendarSystem.Iso.GetDaysInMonth(2012, 2); 34 | } 35 | 36 | #if !V1 37 | [Benchmark] 38 | public void GetDaysSinceEpoch_InOptimizedRange() 39 | { 40 | IsoCalculator.GetDaysSinceEpoch(SampleOptimizedYearMonthDay); 41 | } 42 | 43 | [Benchmark] 44 | public void GetDaysSinceEpoch_OutsideOptimizedRange() 45 | { 46 | IsoCalculator.GetDaysSinceEpoch(SampleNotOptimizedYearMonthDay); 47 | } 48 | 49 | [Benchmark] 50 | public void GetStartOfYearInDays_InOptimizedRange() 51 | { 52 | IsoCalculator.GetStartOfYearInDays(2000); 53 | } 54 | 55 | [Benchmark] 56 | public void GetStartOfYearInDays_OutsideOptimizedRange() 57 | { 58 | IsoCalculator.GetStartOfYearInDays(1600); 59 | } 60 | #endif 61 | } 62 | } 63 | --------------------------------------------------------------------------------