[GH-ISSUE #17] Expiration Date is not correctly compared #13

Open
opened 2026-02-26 01:35:46 +03:00 by kerem · 2 comments
Owner

Originally created by @psovit on GitHub (Aug 13, 2020).
Original GitHub issue: https://github.com/junian/Standard.Licensing/issues/17

The expiration date is set as Universal date when creating the License file (ToUniversalTime()).

But the LicenseValidationDate extension method ExpirationDate is comparing with DateTime.Now.
Shouldn't they both be consistently UniversalTime?

Originally created by @psovit on GitHub (Aug 13, 2020). Original GitHub issue: https://github.com/junian/Standard.Licensing/issues/17 The expiration date is set as Universal date when creating the License file (`ToUniversalTime()`). But the `LicenseValidationDate` extension method `ExpirationDate` is comparing with `DateTime.Now`. Shouldn't they both be consistently UniversalTime?
Author
Owner

@skst commented on GitHub (Feb 23, 2025):

The Expiration property is in UTC. The ExpirationDate() method compares the UTC value of Expiration with the local DateTime.Now value.

The workaround is to use the second ExpirationDate(DateTime) method and pass a UTC value.

Personally, I think Expiration should be a DateOnly and the comparison should be against the local date.

Another issue is that when the Expiration property parses the DateTime value from the XML license file, the Kind property is left as Local. The ParseExact() method needs to add the DateTimeStyles.AdjustToUniversal style.

        public ILicenseBuilder ExpiresAt(DateTime date)
        {
            license.Expiration = date.ToUniversalTime();
            return this;
        }
        public static IValidationChain ExpirationDate(this IStartValidationChain validationChain)
        {
            return ExpirationDate(validationChain, DateTime.Now);
        }

        public static IValidationChain ExpirationDate(this IStartValidationChain validationChain, DateTime systemDateTime)
        {
            var validationChainBuilder = (validationChain as ValidationChainBuilder);
            var validator = validationChainBuilder.StartValidatorChain();
            validator.Validate = license => license.Expiration > systemDateTime;

            validator.FailureResult = new LicenseExpiredValidationFailure()
            {
                Message = "Licensing for this product has expired!",
                HowToResolve = @"Your license is expired. Please contact your distributor/vendor to renew the license."
            };

            return validationChainBuilder;
        }
<!-- gh-comment-id:2677173673 --> @skst commented on GitHub (Feb 23, 2025): The `Expiration` property is in UTC. The `ExpirationDate()` method compares the UTC value of `Expiration` with the local `DateTime.Now` value. The workaround is to use the second `ExpirationDate(DateTime)` method and pass a UTC value. Personally, I think `Expiration` should be a `DateOnly` and the comparison should be against the local date. Another issue is that when the `Expiration` property parses the DateTime value from the XML license file, the `Kind` property is left as `Local`. The `ParseExact()` method needs to add the `DateTimeStyles.AdjustToUniversal` style. ```` public ILicenseBuilder ExpiresAt(DateTime date) { license.Expiration = date.ToUniversalTime(); return this; } ```` ```` public static IValidationChain ExpirationDate(this IStartValidationChain validationChain) { return ExpirationDate(validationChain, DateTime.Now); } public static IValidationChain ExpirationDate(this IStartValidationChain validationChain, DateTime systemDateTime) { var validationChainBuilder = (validationChain as ValidationChainBuilder); var validator = validationChainBuilder.StartValidatorChain(); validator.Validate = license => license.Expiration > systemDateTime; validator.FailureResult = new LicenseExpiredValidationFailure() { Message = "Licensing for this product has expired!", HowToResolve = @"Your license is expired. Please contact your distributor/vendor to renew the license." }; return validationChainBuilder; } ````
Author
Owner

@skst commented on GitHub (Feb 27, 2025):

I have created PR #47 to fix this.

<!-- gh-comment-id:2688766912 --> @skst commented on GitHub (Feb 27, 2025): I have created PR #47 to fix this.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/Standard.Licensing#13
No description provided.