[英]Format a phone Number
我想格式化一个电话号码,电话号码的长度不固定,但它应该在 7-15 位数字之间。
我需要在 Like 1234-567-8中格式化这个12345678
如果有任何数字增加或减少,它应该在最后被删除。 意味着我想要4Digit-3Digit-ResrtOFDigit
假设您的字符串至少包含 8 个字符。
string str = "123456781213123";
if (str.Length > 7)
str = str.Substring(0, 4) + "-" + str.Substring(4, 3) + "-" + str.Substring(7);
str
将举行
1234-567-81213123
LibPhoneNumber
:它由 Google 积极维护,因为它在 Android 和 Google 自己的在线服务中用于格式化电话号码。
libphonenumber
是一个 Java 项目,但 Google确实维护了 libphonenumber 的官方 C#/.NET 端口作为libphonenumber
libphonenumber-csharp
,我将在下面进行演示。Google.LibPhoneNumber
- 这是一个旧的和过时的 NuGet package 最后更新于 2016 年。libphonenumber
(及其libphonenumber-sharp
端口)非常棒,因为它可以简单轻松地以人类可读的“国家”形式格式化任何国家/地区的电话号码,将数字标准化为E.164 格式以实现互操作性使用 SIP/POTS/电话系统并存储在数据库中。
下面是一个如何将libphonenumber
用作 DI 服务的简单示例:
将下面的interface IPhoneNumberService
和class GoogleLpnPhoneNumberService
复制并粘贴到您的项目中:
using global::PhoneNumbers;
public interface IPhoneNumberService
{
/// <summary>Returns <see langword="null"/> when <paramref name="input"/> could not be umambiguously parsed as a valid phone number.</summary>
/// <param name="defaultRegion">This parameter must be the ISO 3166 alpha-2 code for the default region to assume the input phone number belongs to when it does not contain a country dialing code - If <paramref name="input"/> contains a country dialing code then this parameter is ignored. Must not be null.</param>
/// <exception cref="ArgumentException">Thrown when <paramref name="defaultRegion"/> is null or otherwise is not a valid region code.</exception>
( String input, String national, String e164, String? region, String? geoDesc )? ParseAndFormatPhoneNumber( String? input, String defaultRegion = "US" );
#region Convenience methods // Requires C# 8.0 or higher. For .NET Framework move this code to extension methods.
IReadOnlySet<String> SupportedRegions { get; }
/// <summary>Convenience method.</summary>
public Boolean TryFormatUSPhoneNumber( String? input, [NotNullWhen(true)] out String? nationalFormat, [NotNullWhen(true)] out String? e164 )
{
return this.TryFormatPhoneNumber( defaultRegion: "US", input: input, nationalFormat: out nationalFormat, e164: out e164 );
}
/// <summary>
/// Convenience method.<br />
/// Unlike <see cref="ParseAndFormatPhoneNumber"/> this method does not throw <see cref="ArgumentException"/> when <paramref name="defaultRegion"/> is invalid: this method simply returns <see langword="false"/>.
/// </summary>
public Boolean TryFormatPhoneNumber( String defaultRegion, String? input, [NotNullWhen(true)] out String? nationalFormat, [NotNullWhen(true)] out String? e164 )
{
// Validate `defaultRegion` first and return-early so `ParseAndFormatPhoneNumber` won't throw.
if( String.IsNullOrWhiteSpace( defaultRegion ) || !this.SupportedRegions.Contains( defaultRegion ) )
{
nationalFormat = null;
e164 = null;
return false;
}
( String input, String national, String e164, String? region, String? geoDesc )? result = this.ParseAndFormatPhoneNumber( input: input, defaultRegion: defaultRegion );
if( result.HasValue )
{
nationalFormat = result.Value.national;
e164 = result.Value.e164;
return true;
}
else
{
nationalFormat = null;
e164 = null;
return false;
}
}
#endregion
}
/// <summary>Implements <see cref="IPhoneNumberService"/> using Google's LibPhoneNumber.</summary>
/// <remarks>This service class is a singleton.</remarks>
public sealed class GoogleLpnPhoneNumberService : IPhoneNumberService
{
public static GoogleLpnPhoneNumberService Instance { get; } = new GoogleLpnPhoneNumberService();
private static readonly PhoneNumberUtil _phoneUtil = PhoneNumberUtil.GetInstance();
private static readonly PhoneNumberOfflineGeocoder _geo = PhoneNumberOfflineGeocoder.GetInstance();
//
private GoogleLpnPhoneNumberService()
{
}
public IReadOnlySet<String> SupportedRegions => _phoneUtil.GetSupportedRegions(); // <-- Careful, this is a mutable HashSet - also, it uses Default (case-sensitive) String comparisons instead of case-insensitive. Grumble.
public ( String input, String national, String e164, String? region, String? geoDesc )? ParseAndFormatPhoneNumber( String? input, String defaultRegion = "US" )
{
if( defaultRegion is null ) throw new ArgumentNullException( nameof(defaultRegion) );
if( !_phoneUtil.GetSupportedRegions().Contains( defaultRegion ) )
{
String msg = "The supplied region code \"" + defaultRegion + "\" is not supported by libphonenumber.";
throw new ArgumentException( message: msg, paramName: nameof(defaultRegion) );
}
//
if( String.IsNullOrWhiteSpace( input ) ) return null;
try
{
PhoneNumber parsedPhoneNumber = _phoneUtil.Parse( numberToParse: input, defaultRegion: defaultRegion );
// Annoyingly, the documentation doesn't say exactly what the value of `defaultRegion` should be (should it be an ITU calling code or an ISO 2-character country code?) but I find "US" works as a sensible default for North American projects, ofc.
if( !_phoneUtil.IsValidNumber( parsedPhoneNumber ) ) return null;
// Re-set the number after reformatting it:
// Formats (see https://javadoc.io/doc/com.googlecode.libphonenumber/libphonenumber/8.10.10 )
// International: E.123, but using local separators (if applicable). "+41 44 668 1800" (Switzerland)
// National : E.123, but using local separators (if applicable). "044 668 1800"
// E164 : Same as International, but without formatting. "+41446681800"
// RFC3966 : Same as International, but using hyphens instead of whitespace and prepends "tel:". "tel:+41-44-668-1800"
String intl = _phoneUtil.Format( parsedPhoneNumber, PhoneNumberFormat.INTERNATIONAL );
String natl = _phoneUtil.Format( parsedPhoneNumber, PhoneNumberFormat.NATIONAL );
String e164 = _phoneUtil.Format( parsedPhoneNumber, PhoneNumberFormat.E164 );
String? actualRegion = _phoneUtil.GetRegionCodeForNumber( parsedPhoneNumber );
String? geoDescription = _geo.GetDescriptionForNumber( parsedPhoneNumber, languageCode: Locale.English );
return ( input, national: natl, e164, actualRegion, geoDesc: geoDescription );
}
catch( NumberParseException )
{
return null;
}
}
}
要使用Microsoft.Extensions.DependencyInjection
注册此服务,请将其添加到您的ConfigureServices
:
public static void ConfigureServices( IServiceCollection services )
{
_ = services.AddSingleton<IPhoneNumberService>( implementationInstance: GoogleLpnPhoneNumberService.Instance );
}
.Dump()
方法是 Linqpad 的一个特性,它会将 object 呈现为编辑器窗格下方的可视化 output。 在代码下方,我发布了 output 的截图。public static void Main()
{
IPhoneNumberService svc = GoogleLpnPhoneNumberService.Instance;
svc.SupportedRegions.Dump();
ExampleTryFormatPhoneNumber( svc, "425-222-1234" , defaultRegion: "US" );
ExampleTryFormatPhoneNumber( svc, "0370 010 0222" , defaultRegion: "GB" );
ExampleTryFormatPhoneNumber( svc, "+44370 010 0222", defaultRegion: "US" );
ExampleParseAndFormatPhoneNumber( svc, "425-222-1234", defaultRegion: "US" );
ExampleParseAndFormatPhoneNumber( svc, "+44370 010 0222", defaultRegion: "US" );
}
public static void ExampleTryFormatPhoneNumber( IPhoneNumberService svc, String input, String defaultRegion )
{
if( svc.TryFormatPhoneNumber( defaultRegion: defaultRegion, input: input, nationalFormat: out String? natlFmt, e164: out String? e164 ) )
{
( new { Input = input, NationalFormat = natlFmt, E164 = e164 } ).Dump( "Parsed OK!" );
}
else
{
( new { Input = input, NationalFormat = (String?)null, E164 = (String?)null } ).Dump( "Failed to parse." );
}
}
public static void ExampleParseAndFormatPhoneNumber( IPhoneNumberService svc, String input, String defaultRegion )
{
( String input, String national, String e164, String? region, String? geoDesc )? result = svc.ParseAndFormatPhoneNumber( input: input, defaultRegion: defaultRegion );
if( result.HasValue )
{
( new { Input = input, NationalFormat = result.Value.national, E164 = result.Value.e164, Region = result.Value.region, GeoDesc = result.Value.geoDesc } ).Dump( "Failed to parse." );
}
else
{
( new { Input = input, NationalFormat = (String?)null, E164 = (String?)null, Region = (String?)null, GeoDesc = (String?)null } ).Dump( "Failed to parse." );
}
}
Output:
一些注意事项:*
Google.LibPhoneNumber
NuGet package 是原始 Java libphonenumber
的直接 C#/.NET 端口,它通过将 Java 惯用语携带到 C# 代码中显示其传统,例如...
GetInstance()
getter 方法而不是 getter 属性。using global::PhoneNumbers;
.TryParse
方法,而是依赖于使用try/catch(NumberParseException)
的消费代码,*抱怨*我得到了解决方案:
private static string FormatePhoneNumber(string phoneNumber_)
{
return Regex.Replace(phoneNumber_, @"(\d{4})(\d{3})(\d{" + (phoneNumber_.Length - 7).ToString() + "})", "$1-$2" + ((phoneNumber_.Length - 7) == 0 ? "" : "-$3"));
}
谢谢你的帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.