PCL Xamarin.Formsプロジェクトを実行しているときに、DateTime
objectをデバイスのデフォルトの日時形式の文字列にフォーマットするには、展開ターゲットにiOS、AndroidおよびWindowsを含めます。
DateTime.ToShortString()
は、この thread および-- bug に従って、MSDN要件に従って機能しません。
フォームベースのソリューションはありますか、それともプラットフォーム固有のプロジェクトから取得する必要がありますか?
Androidの場合、DIを使用してネイティブプロジェクトから以下を実行できます。
String format = Settings.System.GetString(this.context.ContentResolver
, Settings.System.DateFormat);
string shortDateString = dateTime.ToString(format);
または私もこれを使用できます(以下のコードのC#バージョン):
DateFormat dateFormat = Android.text.format.DateFormat.getDateFormat(context);
this SO質問を参照して、要件をより明確に理解してください(Androidの場合のみです。これはXamarin.Formsの質問なので、すべてのプラットフォームで必要です)。
XamarinフォームのDatePicker
とTimePicker
は日付と時刻をデバイス形式で表示するので、PCLで取得する方法があるといいのですが。
また、PCLには、プラットフォームやイディオムなどの情報を持つDevice
クラスがあります。
PCLの実装が見つからなかったため、DIを使用して要件を実装しました。
PCLでの使用法:
DependencyService.Get<IDeviceInfoService>()?.ConvertToDeviceTimeFormat(DateTime.Now);
DependencyService.Get<IDeviceInfoService>()?.ConvertToDeviceTimeFormat(DateTime.Now);
PCL:
public interface IDeviceInfoService
{
string ConvertToDeviceShortDateFormat(DateTime inputDateTime);
string ConvertToDeviceTimeFormat(DateTime inputDateTime);
}
Android:
[Assembly: Dependency(typeof(DeviceInfoServiceImplementation))]
namespace Droid.Services
{
public class DeviceInfoServiceImplementation : IDeviceInfoService
{
public string ConvertToDeviceShortDateFormat(DateTime inputDateTime)
{
var dateFormat = Android.Text.Format.DateFormat.GetDateFormat(Android.App.Application.Context);
var epochDateTime = Helper.ConvertDateTimeToUnixTime(inputDateTime, true);
if (epochDateTime == null)
{
return string.Empty;
}
using (var javaDate = new Java.Util.Date((long)epochDateTime))
{
return dateFormat.Format(javaDate);
}
}
public string ConvertToDeviceTimeFormat(DateTime inputDateTime)
{
var timeFormat = Android.Text.Format.DateFormat.GetTimeFormat(Android.App.Application.Context);
var epochDateTime = Helper.ConvertDateTimeToUnixTime(inputDateTime, true);
if (epochDateTime == null)
{
return string.Empty;
}
using (var javaDate = new Java.Util.Date((long)epochDateTime))
{
return timeFormat.Format(javaDate);
}
}
}
}
iOS:
[Assembly: Dependency(typeof(DeviceInfoServiceImplementation))]
namespace iOS.Services
{
public class DeviceInfoServiceImplementation : IDeviceInfoService
{
public string ConvertToDeviceShortDateFormat(DateTime inputDateTime)
{
var timeInEpoch = Helper.ConvertDateTimeToUnixTime(inputDateTime);
if (timeInEpoch == null)
{
return string.Empty;
}
using (var dateInNsDate = NSDate.FromTimeIntervalSince1970((double)timeInEpoch))
{
using (var formatter = new NSDateFormatter
{
TimeStyle = NSDateFormatterStyle.None,
DateStyle = NSDateFormatterStyle.Short,
Locale = NSLocale.CurrentLocale
})
{
return formatter.ToString(dateInNsDate);
}
}
}
public string ConvertToDeviceTimeFormat(DateTime inputDateTime)
{
var timeInEpoch = Helper.ConvertDateTimeToUnixTime(inputDateTime);
if (timeInEpoch == null)
{
return string.Empty;
}
using (var dateInNsDate = NSDate.FromTimeIntervalSince1970((double)timeInEpoch))
{
using (var formatter = new NSDateFormatter
{
TimeStyle = NSDateFormatterStyle.Short,
DateStyle = NSDateFormatterStyle.None,
Locale = NSLocale.CurrentLocale
})
{
return formatter.ToString(dateInNsDate);
}
}
}
}
}
ウィンドウズ :
[Assembly: Dependency(typeof(DeviceInfoServiceImplementation))]
namespace WinPhone.Services
{
public class DeviceInfoServiceImplementation : IDeviceInfoService
{
public string ConvertToDeviceShortDateFormat(DateTime inputDateTime)
{
return inputDateTime.ToShortDateString();
}
public string ConvertToDeviceTimeFormat(DateTime inputDateTime)
{
return inputDateTime.ToShortTimeString();
}
}
}
ヘルパーメソッド:
private static readonly DateTime EpochDateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static long? ConvertDateTimeToUnixTime(DateTime? date, bool isDatarequiredInMilliSeconds = false, DateTimeKind dateTimeKind = DateTimeKind.Local) => date.HasValue == false
? (long?)null
: Convert.ToInt64((DateTime.SpecifyKind(date.Value, dateTimeKind).ToUniversalTime() - EpochDateTime).TotalSeconds) * (isDatarequiredInMilliSeconds ? 1000 : 1);
現在のXamarinフォームバージョンでは、次のことを試すことができます。
// This does not work with PCL
var date1 = DateTime.Now.ToShortDateString();
これにより、デバイスのロケールに固有の形式で日付が提供され、プラットフォーム間で機能します。
または:
var date1 = DateTime.Now.ToString(CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern);
特定の形式については、以下を試すことができます。
var date1 = DateTime.Now.ToString("dd-MM-yyyy");
最初と最後のものは私にはかなりクールに見えます。ただし、PCLで機能するのは2番目と3番目のオプションのみです。