Format DateTime in Xamarin Forms to Device Format string

16,099

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

Solution 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.

Share:
16,099
Rohit Vipin Mathews
Author by

Rohit Vipin Mathews

Xamarin Developer (Forms / Android / iOS / Windows) Full Stack .NET Developer (ASP.NET / MVC / WebAPI / WPF / WinForms / MS SQL / .NET Core) Linked In

Updated on June 05, 2022

Comments

  • Rohit Vipin Mathews
    Rohit Vipin Mathews about 2 years

    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.