add date and time formatting methods to localize service (#1616)

- uses Apple APIs for formatting on iOS
- uses .Net APIs for formatting Android
- implemented across project
- remove unnecesary calls to DateTimeConverter
This commit is contained in:
Jake Fink 2021-10-28 12:52:41 -04:00 committed by GitHub
parent 397250368a
commit 83fd6736f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 72 additions and 11 deletions

View File

@ -98,5 +98,15 @@ namespace Bit.Droid.Services
Console.WriteLine(".NET Fallback Language/Locale:" + netLanguage + " (application-specific)");
return netLanguage;
}
public string GetLocaleShortDate(DateTime? date)
{
return date?.ToShortDateString() ?? string.Empty;
}
public string GetLocaleShortTime(DateTime? time)
{
return time?.ToShortTimeString() ?? string.Empty;
}
}
}

View File

@ -1,9 +1,22 @@
using System.Globalization;
using System;
using System.Globalization;
namespace Bit.App.Abstractions
{
public interface ILocalizeService
{
CultureInfo GetCurrentCultureInfo();
/// <summary>
/// Format date using device locale.
/// Needed for iOS as it provides locales unsupported in .Net
/// </summary>
string GetLocaleShortDate(DateTime? date);
/// <summary>
/// Format time using device locale.
/// Needed for iOS as it provides locales unsupported in .Net
/// </summary>
string GetLocaleShortTime(DateTime? time);
}
}

View File

@ -17,7 +17,6 @@
<ContentPage.Resources>
<ResourceDictionary>
<u:DateTimeConverter x:Key="dateTime" />
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
x:Name="_closeItem" x:Key="closeItem" />
<StackLayout

View File

@ -26,6 +26,7 @@ namespace Bit.App.Pages
private readonly ISyncService _syncService;
private readonly IBiometricService _biometricService;
private readonly IPolicyService _policyService;
private readonly ILocalizeService _localizeService;
private const int CustomVaultTimeoutValue = -100;
@ -72,6 +73,7 @@ namespace Bit.App.Pages
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
_biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService");
_policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
GroupedItems = new ExtendedObservableCollection<SettingsPageListGroup>();
PageTitle = AppResources.Settings;
@ -86,8 +88,9 @@ namespace Bit.App.Pages
if (lastSync != null)
{
lastSync = lastSync.Value.ToLocalTime();
_lastSyncDate = string.Format("{0} {1}", lastSync.Value.ToShortDateString(),
lastSync.Value.ToShortTimeString());
_lastSyncDate = string.Format("{0} {1}",
_localizeService.GetLocaleShortDate(lastSync.Value),
_localizeService.GetLocaleShortTime(lastSync.Value));
}
if (await _policyService.PolicyAppliesToUser(PolicyType.MaximumVaultTimeout))

View File

@ -14,6 +14,7 @@ namespace Bit.App.Pages
private readonly IPlatformUtilsService _platformUtilsService;
private readonly IStorageService _storageService;
private readonly ISyncService _syncService;
private readonly ILocalizeService _localizeService;
private string _lastSync = "--";
private bool _inited;
@ -25,6 +26,7 @@ namespace Bit.App.Pages
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
PageTitle = AppResources.Sync;
}
@ -68,7 +70,9 @@ namespace Bit.App.Pages
if (last != null)
{
var localDate = last.Value.ToLocalTime();
LastSync = string.Format("{0} {1}", localDate.ToShortDateString(), localDate.ToShortTimeString());
LastSync = string.Format("{0} {1}",
_localizeService.GetLocaleShortDate(localDate),
_localizeService.GetLocaleShortTime(localDate));
}
else
{

View File

@ -17,7 +17,6 @@
<ContentPage.Resources>
<ResourceDictionary>
<u:DateTimeConverter x:Key="dateTime" />
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
x:Name="_closeItem" x:Key="closeItem" />
<StackLayout

View File

@ -25,6 +25,7 @@ namespace Bit.App.Pages
private readonly IMessagingService _messagingService;
private readonly IEventService _eventService;
private readonly IPasswordRepromptService _passwordRepromptService;
private readonly ILocalizeService _localizeService;
private CipherView _cipher;
private List<ViewPageFieldViewModel> _fields;
private bool _canAccessPremium;
@ -52,6 +53,7 @@ namespace Bit.App.Pages
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
_passwordRepromptService = ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService");
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
CopyCommand = new Command<string>((id) => CopyAsync(id, null));
CopyUriCommand = new Command<LoginUriView>(CopyUri);
CopyFieldCommand = new Command<FieldView>(CopyField);
@ -152,8 +154,8 @@ namespace Bit.App.Pages
fs.Spans.Add(new Span
{
Text = string.Format(" {0} {1}",
Cipher.RevisionDate.ToLocalTime().ToShortDateString(),
Cipher.RevisionDate.ToLocalTime().ToShortTimeString())
_localizeService.GetLocaleShortDate(Cipher.RevisionDate.ToLocalTime()),
_localizeService.GetLocaleShortTime(Cipher.RevisionDate.ToLocalTime()))
});
return fs;
}
@ -171,8 +173,8 @@ namespace Bit.App.Pages
fs.Spans.Add(new Span
{
Text = string.Format(" {0} {1}",
Cipher.PasswordRevisionDisplayDate?.ToLocalTime().ToShortDateString(),
Cipher.PasswordRevisionDisplayDate?.ToLocalTime().ToShortTimeString())
_localizeService.GetLocaleShortDate(Cipher.PasswordRevisionDisplayDate?.ToLocalTime()),
_localizeService.GetLocaleShortTime(Cipher.PasswordRevisionDisplayDate?.ToLocalTime()))
});
return fs;
}

View File

@ -1,10 +1,19 @@
using System;
using Bit.App.Abstractions;
using Bit.Core.Utilities;
using Xamarin.Forms;
namespace Bit.App.Utilities
{
public class DateTimeConverter : IValueConverter
{
private readonly ILocalizeService _localizeService;
public DateTimeConverter()
{
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
}
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
@ -17,7 +26,9 @@ namespace Bit.App.Utilities
return string.Empty;
}
var d = ((DateTime)value).ToLocalTime();
return string.Format("{0} {1}", d.ToShortDateString(), d.ToShortTimeString());
return string.Format("{0} {1}",
_localizeService.GetLocaleShortDate(d),
_localizeService.GetLocaleShortTime(d));
}
public object ConvertBack(object value, Type targetType, object parameter,

View File

@ -100,5 +100,25 @@ namespace Bit.iOS.Core.Services
Console.WriteLine(".NET Fallback Language/Locale:" + netLanguage + " (application-specific)");
return netLanguage;
}
public string GetLocaleShortDate(DateTime? date)
{
using (var df = new NSDateFormatter())
{
df.Locale = NSLocale.CurrentLocale;
df.DateStyle = NSDateFormatterStyle.Short;
return df.StringFor((NSDate)date);
}
}
public string GetLocaleShortTime(DateTime? time)
{
using (var df = new NSDateFormatter())
{
df.Locale = NSLocale.CurrentLocale;
df.TimeStyle = NSDateFormatterStyle.Short;
return df.StringFor((NSDate)time);
}
}
}
}