Skip to content

Commit 3f28f4d

Browse files
committed
Write WKT coordinates with invariant culture (#3820)
Fixes #3819
1 parent 6c1ba1f commit 3f28f4d

File tree

3 files changed

+138
-7
lines changed

3 files changed

+138
-7
lines changed

src/Nest/QueryDsl/Geo/WKT/GeoWKTWriter.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using System.Globalization;
23
using System.Linq;
34
using System.Text;
45

@@ -135,13 +136,13 @@ private static void WriteEnvelope(IEnvelopeGeoShape envelope, StringBuilder buil
135136

136137
// WKT specification expects the following order: minLon, maxLon, maxLat, minLat.
137138
// envelope is top_left (minLon, maxLat), bottom_right (maxLon, minLat)
138-
builder.Append(topLeft.Longitude)
139+
builder.Append(topLeft.Longitude.ToString(CultureInfo.InvariantCulture))
139140
.Append(", ")
140-
.Append(bottomRight.Longitude)
141+
.Append(bottomRight.Longitude.ToString(CultureInfo.InvariantCulture))
141142
.Append(", ")
142-
.Append(topLeft.Latitude)
143+
.Append(topLeft.Latitude.ToString(CultureInfo.InvariantCulture))
143144
.Append(", ")
144-
.Append(bottomRight.Latitude)
145+
.Append(bottomRight.Latitude.ToString(CultureInfo.InvariantCulture))
145146
.Append(")");
146147
}
147148

@@ -176,12 +177,12 @@ private static void WriteCoordinates(IEnumerable<GeoCoordinate> coordinates, Str
176177

177178
private static void WriteCoordinate(GeoCoordinate coordinate, StringBuilder builder)
178179
{
179-
builder.Append(coordinate.Longitude)
180+
builder.Append(coordinate.Longitude.ToString(CultureInfo.InvariantCulture))
180181
.Append(" ")
181-
.Append(coordinate.Latitude);
182+
.Append(coordinate.Latitude.ToString(CultureInfo.InvariantCulture));
182183

183184
if (coordinate.Z.HasValue)
184-
builder.Append(" ").Append(coordinate.Z.Value);
185+
builder.Append(" ").Append(coordinate.Z.Value.ToString(CultureInfo.InvariantCulture));
185186
}
186187
}
187188
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Elastic.Xunit.XunitPlumbing;
2+
using FluentAssertions;
3+
using Nest;
4+
5+
namespace Tests.Reproduce
6+
{
7+
public class GitHubIssue3819
8+
{
9+
[U]
10+
[UseCulture("fr-FR")]
11+
public void WriteWKTCoordinatesWithInvariantCulture()
12+
{
13+
var wkt = "POINT (45.1 42.25)";
14+
15+
var shape = GeoWKTReader.Read(wkt);
16+
var actual = GeoWKTWriter.Write(shape);
17+
actual.Should().Be(wkt);
18+
}
19+
}
20+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#region License
2+
// Copyright (c) .NET Foundation and Contributors
3+
// All Rights Reserved
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
//
17+
// https://github.com/xunit/samples.xunit/blob/master/UseCulture/UseCultureAttribute.cs
18+
#endregion
19+
20+
using System;
21+
using System.Globalization;
22+
using System.Reflection;
23+
using System.Threading;
24+
using Xunit.Sdk;
25+
26+
namespace Tests.Reproduce
27+
{
28+
/// <summary>
29+
/// Apply this attribute to your test method to replace the
30+
/// <see cref="Thread.CurrentThread" /> <see cref="CultureInfo.CurrentCulture" /> and
31+
/// <see cref="CultureInfo.CurrentUICulture" /> with another culture.
32+
/// </summary>
33+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
34+
public class UseCultureAttribute : BeforeAfterTestAttribute
35+
{
36+
private readonly Lazy<CultureInfo> _culture;
37+
private readonly Lazy<CultureInfo> _uiCulture;
38+
39+
private CultureInfo _originalCulture;
40+
private CultureInfo _originalUiCulture;
41+
42+
/// <summary>
43+
/// Replaces the culture and UI culture of the current thread with
44+
/// <paramref name="culture" />
45+
/// </summary>
46+
/// <param name="culture">The name of the culture.</param>
47+
/// <remarks>
48+
/// <para>
49+
/// This constructor overload uses <paramref name="culture" /> for both
50+
/// <see cref="Culture" /> and <see cref="UICulture" />.
51+
/// </para>
52+
/// </remarks>
53+
public UseCultureAttribute(string culture)
54+
: this(culture, culture) { }
55+
56+
/// <summary>
57+
/// Replaces the culture and UI culture of the current thread with
58+
/// <paramref name="culture" /> and <paramref name="uiCulture" />
59+
/// </summary>
60+
/// <param name="culture">The name of the culture.</param>
61+
/// <param name="uiCulture">The name of the UI culture.</param>
62+
public UseCultureAttribute(string culture, string uiCulture)
63+
{
64+
_culture = new Lazy<CultureInfo>(() => new CultureInfo(culture, false));
65+
_uiCulture = new Lazy<CultureInfo>(() => new CultureInfo(uiCulture, false));
66+
}
67+
68+
/// <summary>
69+
/// Gets the culture.
70+
/// </summary>
71+
public CultureInfo Culture => _culture.Value;
72+
73+
/// <summary>
74+
/// Gets the UI culture.
75+
/// </summary>
76+
public CultureInfo UICulture => _uiCulture.Value;
77+
78+
/// <summary>
79+
/// Stores the current <see cref="Thread.CurrentPrincipal" />
80+
/// <see cref="CultureInfo.CurrentCulture" /> and <see cref="CultureInfo.CurrentUICulture" />
81+
/// and replaces them with the new cultures defined in the constructor.
82+
/// </summary>
83+
/// <param name="methodUnderTest">The method under test</param>
84+
public override void Before(MethodInfo methodUnderTest)
85+
{
86+
_originalCulture = Thread.CurrentThread.CurrentCulture;
87+
_originalUiCulture = Thread.CurrentThread.CurrentUICulture;
88+
89+
Thread.CurrentThread.CurrentCulture = Culture;
90+
Thread.CurrentThread.CurrentUICulture = UICulture;
91+
92+
CultureInfo.CurrentCulture.ClearCachedData();
93+
CultureInfo.CurrentUICulture.ClearCachedData();
94+
}
95+
96+
/// <summary>
97+
/// Restores the original <see cref="CultureInfo.CurrentCulture" /> and
98+
/// <see cref="CultureInfo.CurrentUICulture" /> to <see cref="Thread.CurrentPrincipal" />
99+
/// </summary>
100+
/// <param name="methodUnderTest">The method under test</param>
101+
public override void After(MethodInfo methodUnderTest)
102+
{
103+
Thread.CurrentThread.CurrentCulture = _originalCulture;
104+
Thread.CurrentThread.CurrentUICulture = _originalUiCulture;
105+
106+
CultureInfo.CurrentCulture.ClearCachedData();
107+
CultureInfo.CurrentUICulture.ClearCachedData();
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)