-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[Core] Fixes conversion binding a DateTime to a string if the locale is not the US #3700
Conversation
build --uitests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ConvertIsCultureInvariant
unit test is failing
I will look at this, but I think it's not a matter of using the current locale while converting (there are good reasons why we do not) and more a matter of string formatting. |
build --uitests |
public static Action<decimal> DecimalChange; | ||
} | ||
|
||
void UpdateDescLabel() => descLabel.Text = $"{_instuctions}{Thread.CurrentThread.CurrentCulture.DisplayName}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I run this on Android, I don't see the current culture on the page.
DateTime _testDate = DateTime.ParseExact("2077-12-31T13:55:56", "yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture); | ||
int _localeIndex = 0; | ||
string[] _localeIds = new[] { "en-US", "pt-PT", "ru-RU", "en-AU", "zh-Hans" }; | ||
string _instuctions = $"When you change the locale, the date format must change.{Environment.NewLine}Current locale: "; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_instuctions >> _instructions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a feature request to me; The existing behavior is expected. We have code that explicitly checks that we're using the invariant culture. Now, that's not to say we should stick with that behavior but to change it would be a feature and would have to be opt-in unless we decide it won't break anyone.
The new behavior, allowing culture specific conversions, should be applied to all renderers and so would require a horizontal audit of all renderers as well as tests for all newly culturally aware renderers.
// people write numbers using the separator accepted in their locale | ||
var ds = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator; | ||
vm.Text = $"0{ds}7"; | ||
Assert.That(slider.Value, Is.EqualTo(0.7)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test explicitly expects the invariant culture is used when displaying the slider value. This would lead me to believe the original developer thought about Culture and decided to go with the invariant culture everywhere. So this PR is less of a "fix" and more of a feature request; The current behavior is "expected" from the perspective of the original developer. As a feature request, the work item would be to review all renderers and re-establish a new expected behavior wrt culture -- which is to say that it should respect whatever culture the main thread is using.
@@ -317,7 +318,7 @@ internal bool TryConvert(ref object value) | |||
TypeConverter typeConverterTo; | |||
if (SimpleConvertTypes.TryGetValue(valueType, out convertableTo) && Array.IndexOf(convertableTo, type) != -1) | |||
{ | |||
value = Convert.ChangeType(value, type); | |||
value = Convert.ChangeType(value, type, System.Globalization.CultureInfo.CurrentCulture); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With any luck the feature "Use UI Thread Culture When Preforming Conversions" would only require changes in this function. Who knows, maybe this is the only spot! However, right below, we have a ConvertFromInvariantString
so we'd have to go and understand if that also needs to be updated to take the UI culture.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Below seems to be a mistake, because the ToString
method must use current culture. Therefore, we can't converted from an invariant culture. But there are known types that do not depend on localization and the mistake is not manifested.
{ | ||
// see: https://bugzilla.xamarin.com/show_bug.cgi?id=32871 | ||
// do not canonicalize "*.[.]"; "1." should not update bound BindableProperty | ||
if (stringValue.EndsWith(".")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic should probably be updated to test if the string value ends with the CurrentCulture
decimal separator instead of the hard coded dot. Even if we stick with invariant culture we should replace the hardcoded dot with the NumberDecimalSeparator
.
throw new FormatException(); | ||
|
||
// to change locale if stringValue contains decimal separator for that locale | ||
if (stringValue.IndexOf(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator) != -1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be removed; We shouldn't infer a culture by testing for culture specific values in the string. If we decide to allow non-invariant culture then we'll simply get the culture from the UI thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm with @kingces95 on this one. This has been discussed in the past, and decided to stick with the current behavior.
One of the risk I recalled by doing automagic conversion was the potentiality of corrupting one's string-based data model (think json).
@jassmith Please weight in, and decide to close or not.
I agree with Chris here as well, we should be doing conversions with CurrentCulture. I haven't given this a full review but I thought this was supposed to simply make conversions work with comma cultures when one is active. |
I leave old "expected" behavior by default, nothing to break. To use current locale for a specific property, you also must enable it. Ex:. |
@paymicro Thanks for this feature. We appreciate the amount of time you spent on it, and understand your will and energy for making Xamarin.Forms easier to use for everyone. Unfortunately, we need more time to think about this and evaluate all the consequences of those changes, and a pull-request is not the right place to discuss those. So, I'm closing this PR. It's not a Feel free to write a spec for your proposed change and we'll happily discuss it in an issue. |
Description of Change
Fixed converting the date without regard to the installed locale.
You can install the locale using the following code:
Issues Resolved
API Changes
None
Platforms Affected
Behavioral/Visual Changes
Simple types correctly converts to a string from binding context.
Before/After Screenshots
Before
After
Testing Procedure
PR Checklist