Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DateTime operators to SYSTEMTIME #672

Merged
merged 2 commits into from
Sep 6, 2022
Merged

Conversation

elachlan
Copy link
Contributor

@elachlan elachlan commented Aug 26, 2022

Fixes #667 and #673

Copy link
Member

@AArnott AArnott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for getting this started.

src/Microsoft.Windows.CsWin32/Generator.cs Show resolved Hide resolved
Comment on lines 5 to 16
if (sysTime.wYear <= 0 || sysTime.wMonth <= 0 || sysTime.wDay <= 0)
{
Debug.Fail("Incorrect SYSTEMTIME info!");
return global::System.DateTime.MinValue;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is acceptable to just return DateTime.MinValue in an error condition. For WinForms they're free to swallow errors if they want, but we can't do that in a general system like this.

An interesting scenario that this check includes (among others) is default(SYSTEMTIME), which evidently cannot be converted. Maybe we could do something special where we say if (sysTime == default) return default; in both conversion operators. Then at least structs with all zeros can convert between each other with no information loss and no exception. At that point, exceptions only get thrown when there is actually invalid data set into the struct.
Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an aside, given this will be different behavior from what WinForms was used to, we should call out to them when they adopt this that it's different, and they should carefully review where they rely on their old implicit conversion operator to avoid regressions.
This BTW is an argument for not declaring implicit operators except where they can be trivially implemented. I'm still on the fence as to whether these should be implicit or explicit. When explicit, it would be far easier for WinForms to audit their code (because errors will be everywhere they used to use their implicit ones) and either allow use of an explicit operator or call into a method they define that retains their old proprietary behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I have implemented what you asked. Did we want to keep the default and the year/month/day comparison separate and throw an exception when those values are invalid?

I think they should be explicit. SYSTEMTIME for year "The valid values for this member are 1601 through 30827."
https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime

For DateTime "The year, between 1 and 9999."
https://docs.microsoft.com/en-us/dotnet/api/system.datetime.year?view=net-6.0

We will get data loss when converting between them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will get data loss when converting between them.

If data loss is inevitable, they should not be implicit conversion operators.
If we work for all arguably valid data, and can throw in the unconvertible cases, that may qualify for implicit operators.
Otherwise, explicit operators would probably be better.

src/Microsoft.Windows.CsWin32/templates/SYSTEMTIME.cs Outdated Show resolved Hide resolved
@elachlan elachlan force-pushed the SYSTEMTIME branch 2 times, most recently from 0423e89 to 1cef4b1 Compare August 27, 2022 01:35
sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds);
}

public static explicit operator SYSTEMTIME(global::System.DateTime time)
Copy link
Contributor Author

@elachlan elachlan Aug 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could maybe be implicit. But if it is ever used in a pinvoke it might cause issues because the minimum value for year is 1601.
https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave it as explicit for now. It's safer to move from explicit to implicit later than the other way around.

@AArnott
Copy link
Member

AArnott commented Aug 28, 2022

@elachlan I'm on jury duty last week and next week, FYI. So my participation will be weak and delayed through the end of that.

Add Tests for Template structs
Fix up output formatting
sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds);
}

public static explicit operator SYSTEMTIME(global::System.DateTime time)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave it as explicit for now. It's safer to move from explicit to implicit later than the other way around.

@AArnott AArnott linked an issue Sep 6, 2022 that may be closed by this pull request
@AArnott
Copy link
Member

AArnott commented Sep 6, 2022

Thanks, @elachlan

@AArnott AArnott merged commit 65f78d0 into microsoft:main Sep 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix formatting issues around object initializers Add DateTime operators to SYSTEMTIME
2 participants