Format DateTime in Xamarin Forms to Device Format string

此生再无相见时 提交于 2020-07-02 07:32:19

问题


How can I format a DateTimeobject to a string in the device default datetime format when running a PCL Xamarin.Forms project and my deployement targets include iOS, Android and Windows.

The DateTime.ToShortString() doesn't work as per MSDN requirement according to this thread and this bug.

Is there any Forms based solution or do I need to get it from platform specific projects?

For Android, I can do the following from Native project using DI:

String format = Settings.System.GetString(this.context.ContentResolver 
                                         , Settings.System.DateFormat);
string shortDateString = dateTime.ToString(format);

OR I can use this too (the C# version of the below code):

DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context);

Look into this SO question to understand the requirement more clearly (its only for android, I want it for all platforms as this is a Xamarin.Forms question).

Since the DatePicker and TimePicker in Xamarin Forms show the date and time in device format I am hoping there would a way to get it in the PCL.

Also there is a Device class in PCL which has information like platforms, idiom, etc.


回答1:


As I could not find any PCL implementation I used DI to implement the requirement.

Usage in 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);
                }
            }
        }
    }
}

Windows :

[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();
        }
    }
}

Helper method :

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);



回答2:


With the current Xamarin Forms version, you may try:

// This does not work with PCL
var date1 = DateTime.Now.ToShortDateString();

This gives the date in a format specific to the device's locale and works across platforms.

Alternatively:

var date1 = DateTime.Now.ToString(CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern);

For specific format the following can be tried:

var date1 = DateTime.Now.ToString("dd-MM-yyyy");

The first and the last one look pretty cool to me. But only the second and the third options work with PCL.




回答3:


Very similar to Rohit Vipin Mathews answer but without using helper methods.

For Android

public class DeviceServiceImplementation : IDeviceInfoService
{
    public string FormatTime(DateTime dateTime)
    {
        return DateUtils.FormatDateTime(Application.Context, (long) dateTime.ToUniversalTime()
            .Subtract(DateTime.UnixEpoch).TotalMilliseconds, FormatStyleFlags.ShowTime);
    }
}

For iOS

public class DeviceServiceImplementation : IDeviceInfoService
{
    public string FormatTime(DateTime dateTime)
    {
        using var nsDateFormatter = new NSDateFormatter
        {
            DateStyle = NSDateFormatterStyle.None,
            TimeStyle = NSDateFormatterStyle.Short,
            FormattingContext = NSFormattingContext.Standalone,
            Locale = NSLocale.CurrentLocale
        };
        return nsDateFormatter.StringFor(dateTime.ToNSDate()
            .AddSeconds(-1 * NSTimeZone.SystemTimeZone.GetSecondsFromGMT));
    }
}


来源:https://stackoverflow.com/questions/37835096/format-datetime-in-xamarin-forms-to-device-format-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!