简体   繁体   中英

Format DateTime in Xamarin Forms to Device Format string

How can I format a DateTime object 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.

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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM