在Xamarin Forms中将DateTime格式化为设备格式字符串

13
我如何在运行PCL Xamarin.Forms项目并且我的部署目标包括iOS、Android和Windows时,将DateTime对象格式化为设备默认日期时间格式的字符串?DateTime.ToShortString()不符合MSDN要求,根据这个thread和这个bug。是否有基于Forms的解决方案,或者我需要从特定于平台的项目中获取它?对于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关于这个问题的Stack Overflow帖子,以便更清楚地了解要求(该帖子仅适用于Android,我希望能在所有平台上使用,因为这是一个Xamarin.Forms问题)。
由于Xamarin Forms中的DatePicker和TimePicker显示设备格式的日期和时间,我希望能找到一种方法在PCL中获取它们。
此外,PCL中还有一个Device类,其中包含平台、模式等信息。

如果格式化是特定于客户端的,您可能希望考虑使用依赖项服务。https://developer.xamarin.com/guides/xamarin-forms/dependency-service/introduction/ - Andres Castro
@AndresCastro - 谢谢,但我正在寻找PCL选项,是的,我知道可以通过为每个平台获取DI来完成它。 - Rohit Vipin Mathews
2
我会觉得只需要使用dateTime.ToString("d")这个方法就可以了,因为它会将ToString应用在当前的文化中。但是我并没有测试过这种方法。当你改变设备文化时可能会发生有趣的事情。 - Andres Castro
@AndresCastro - 不是这样的,请查看我所添加的链接。 - Rohit Vipin Mathews
@Rohit,您能否写出您想要的预期输出示例? - jzeferino
如果用户设备的日期格式为“MM/dd/yyyy”,则输出将是“MM/dd/yyyy”,如果用户设备的日期格式为“dd/MM/yyyy”,则需要输出该格式。 - Rohit Vipin Mathews
3个回答

4

由于我找不到任何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);
                }
            }
        }
    }
}

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

辅助方法:

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

使用当前的Xamarin Forms版本,您可以尝试以下操作:

// 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。


0

与Rohit Vipin Mathews的答案非常相似,但不使用辅助方法。

适用于Android

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

适用于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));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接