Получите AM / PM для даты и времени в нижнем регистре, используя только формат datetime
-
20-08-2019 - |
Вопрос
Я хочу получить пользовательский формат даты и времени, включающий обозначение AM / PM, но я хочу, чтобы "AM" или "PM" были в нижнем регистре без сделайте остальные символы строчными.
Возможно ли это с использованием единого формата и без использования регулярного выражения?
Вот что у меня есть прямо сейчас:
item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mmtt")
Примером результата прямо сейчас было бы Суббота, 31 января 2009 года, 13:34
Решение
Я бы лично разделил его на две части:часть, не относящаяся к am / pm, и часть am / pm с меньшим:
string formatted = item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mm") +
item.PostedOn.ToString("tt").ToLower();
Другой вариант (который я рассмотрю через секунду) - захватить текущую DateTimeFormatInfo, создать копию и установить для обозначений am / pm версию в нижнем регистре.Затем используйте эту информацию о формате для обычного форматирования.Очевидно, вы хотели бы кэшировать DateTimeFormatInfo...
Редактировать:Несмотря на мой комментарий, я все равно написал часть о кэшировании.Вероятно, этого не будет быстрее чем приведенный выше код (поскольку он включает блокировку и поиск по словарю), но это упрощает вызывающий код:
string formatted = item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mmtt",
GetLowerCaseInfo());
Вот полная программа для демонстрации:
using System;
using System.Collections.Generic;
using System.Globalization;
public class Test
{
static void Main()
{
Console.WriteLine(DateTime.Now.ToString("dddd, MMMM d, yyyy a\\t h:mmtt",
GetLowerCaseInfo());
}
private static readonly Dictionary<DateTimeFormatInfo,DateTimeFormatInfo> cache =
new Dictionary<DateTimeFormatInfo,DateTimeFormatInfo>();
private static object cacheLock = new object();
public static DateTimeFormatInfo GetLowerCaseInfo()
{
DateTimeFormatInfo current = CultureInfo.CurrentCulture.DateTimeFormat;
lock (cacheLock)
{
DateTimeFormatInfo ret;
if (!cache.TryGetValue(current, out ret))
{
ret = (DateTimeFormatInfo) current.Clone();
ret.AMDesignator = ret.AMDesignator.ToLower();
ret.PMDesignator = ret.PMDesignator.ToLower();
cache[current] = ret;
}
return ret;
}
}
}
Другие советы
Вы могли бы разделить строку формата на две части, а затем ввести в нижний регистр часть AM / PM, вот так:
DateTime now = DateTime.Now;
string nowString = now.ToString("dddd, MMMM d, yyyy a\\t h:mm");
nowString = nowString + now.ToString("tt").ToLower();
Тем не менее, я думаю, что более элегантным решением является использование DateTimeFormatInfo
экземпляр что вы создаете и заменяете AMDesignator
и PMDesignator
свойства с "am" и "pm" соответственно:
DateTimeFormatInfo fi = new DateTimeFormatInfo();
fi.AMDesignator = "am";
fi.PMDesignator = "pm";
string nowString = now.ToString("dddd, MMMM d, yyyy a\\t h:mmtt", fi);
Вы можете использовать DateTimeFormatInfo
экземпляр для настройки многих других аспектов преобразования DateTime
к a string
.
Редактировать:Пример Джона намного лучше, хотя я думаю, что метод расширения по-прежнему является правильным решением, поэтому вам не нужно повторять код повсюду.Я удалил replace и заменил первый пример Джона на место в методе extension.Мои приложения, как правило, являются приложениями для внутренней сети, и мне не нужно беспокоиться о культуре других стран.
Добавьте метод расширения, который сделает это за вас.
public static class DateTimeExtensions
{
public static string MyDateFormat( this DateTime dateTime )
{
return dateTime.ToString("dddd, MMMM d, yyyy a\\t h:mm") +
dateTime.ToString("tt").ToLower();
}
}
...
item.PostedOn.MyDateFormat();
Редактировать:Другие идеи о том, как это сделать, на Как отформатировать дату и время типа "Окт.10, 2008 10:43 утра по восточному времени" в C#.
Проблема с вышеупомянутыми подходами заключается в том, что основная причина, по которой вы используете строку формата, заключается в том, чтобы включить локализацию, а приведенные до сих пор подходы не подойдут для любой страны или культуры, которые не желают включать окончательные am или pm.Итак, что я сделал, так это выписал метод расширения, который понимает дополнительную последовательность форматов 'TT', которая означает строчные буквы am / pm.Приведенный ниже код отлажен для моих случаев, но, возможно, еще не идеален:
/// <summary>
/// Converts the value of the current System.DateTime object to its equivalent string representation using the specified format. The format has extensions over C#s ordinary format string
/// </summary>
/// <param name="dt">this DateTime object</param>
/// <param name="formatex">A DateTime format string, with special new abilities, such as TT being a lowercase version of 'tt'</param>
/// <returns>A string representation of value of the current System.DateTime object as specified by format.</returns>
public static string ToStringEx(this DateTime dt, string formatex)
{
string ret;
if (!String.IsNullOrEmpty(formatex))
{
ret = "";
string[] formatParts = formatex.Split(new[] { "TT" }, StringSplitOptions.None);
for (int i = 0; i < formatParts.Length; i++)
{
if (i > 0)
{
//since 'TT' is being used as the seperator sequence, insert lowercase AM or PM as appropriate
ret += dt.ToString("tt").ToLower();
}
string formatPart = formatParts[i];
if (!String.IsNullOrEmpty(formatPart))
{
ret += dt.ToString(formatPart);
}
}
}
else
{
ret = dt.ToString(formatex);
}
return ret;
}
Это должно быть наиболее эффективным из всех этих вариантов.Но очень жаль, что они не могли использовать опцию нижнего регистра в формате DateTime (tt напротив TT?).
public static string AmPm(this DateTime dt, bool lower = true)
{
return dt.Hour < 12
? (lower ? "am" : "AM")
: (lower ? "pm" : "PM");
}