解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
3.01 KiB
X
using System.Globalization;

namespace NewLife.Data;

/// <summary>经纬度坐标。值类型,栈分配,零GC压力</summary>
/// <remarks>
/// 默认值为 (0,0),即几内亚湾。需要表示"无坐标"时使用 GeoPoint?。
/// 字符串表示 "经度,纬度",如 "116.4,39.9"。
/// </remarks>
public readonly record struct GeoPoint(Double Longitude, Double Latitude)
{
    /// <summary>已重载,输出 "经度,纬度"。使用固定区域性,避免小数点分隔符随系统区域变化</summary>
    /// <returns></returns>
    public override String ToString() => $"{Longitude.ToString(CultureInfo.InvariantCulture)},{Latitude.ToString(CultureInfo.InvariantCulture)}";

    /// <summary>解析经纬度字符串,形如 "116.4,39.9"</summary>
    /// <param name="location">经纬度字符串</param>
    /// <returns>坐标点</returns>
    /// <exception cref="FormatException">字符串为空或格式非法</exception>
    public static GeoPoint Parse(String? location)
    {
        if (!TryParse(location, out var point))
            throw new FormatException($"无效经纬度字符串:{location}");

        return point;
    }

    /// <summary>尝试解析经纬度字符串,形如 "116.4,39.9"</summary>
    /// <param name="location">经纬度字符串</param>
    /// <param name="point">输出坐标点</param>
    /// <returns>是否解析成功</returns>
    public static Boolean TryParse(String? location, out GeoPoint point)
    {
        point = default;
        if (location.IsNullOrEmpty()) return false;

        var ss = location.Split(',');
        if (ss.Length < 2) return false;

        // 与 Utility.ToDouble 一致使用 InvariantCulture,避免小数点分隔符歧义
        if (!Double.TryParse(ss[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var lon)) return false;
        if (!Double.TryParse(ss[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var lat)) return false;

        point = new GeoPoint(lon, lat);
        return true;
    }

    /// <summary>编码坐标点为GeoHash字符串</summary>
    /// <param name="level">字符个数。默认9位字符编码,精度2米</param>
    /// <returns>GeoHash 字符串</returns>
    public String Encode(Int32 level = 9) => GeoHash.Encode(Longitude, Latitude, level);

    /// <summary>解码GeoHash字符串为坐标点</summary>
    /// <param name="hash">GeoHash 字符串</param>
    /// <returns>坐标点</returns>
    public static GeoPoint Decode(String hash)
    {
        var (Longitude, Latitude) = GeoHash.Decode(hash);
        return new(Longitude, Latitude);
    }

    /// <summary>尝试解码GeoHash字符串为坐标点</summary>
    /// <param name="hash">GeoHash 字符串</param>
    /// <param name="point">输出坐标点</param>
    /// <returns>是否解码成功</returns>
    public static Boolean TryDecode(String hash, out GeoPoint point)
    {
        point = default;
        if (!GeoHash.TryDecode(hash, out var lon, out var lat)) return false;

        point = new(lon, lat);
        return true;
    }
}