Получите AM/PM для даты в нижнем регистре, используя только формат даты и времени
Я должен получить пользовательский формат DateTime, включая обозначение AM/PM, но я хочу, чтобы "AM" или "PM" были строчными, без остальной части символов в нижнем регистре.
Возможно ли это использование одного формата и без использования регулярного выражения?
Вот что я получил прямо сейчас:
item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mmtt")
Пример выхода прямо сейчас будет Суббота, 31 января 2009 года в 1:34 вечера
Ответы
Ответ 1
Я бы лично отформатировал его в двух частях: часть non-am/pm и часть am/pm с ToLower:
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;
}
}
}
Ответ 2
Вы можете разбить строку формата на две части, а затем в нижнем регистре часть 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
в string
.
Ответ 3
РЕДАКТИРОВАТЬ: пример Jon намного лучше, хотя я считаю, что метод расширения по-прежнему остается таким, что вам не нужно повторять код везде. Я удалил замену и заменил первый пример Jon на месте в методе расширения. Мои приложения - это, как правило, приложения для интрасети, и мне не нужно беспокоиться о неамериканских культурах.
Добавьте метод расширения для этого.
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();
EDIT: другие идеи о том, как это сделать при Как форматировать DateTime like " 10, 2008 10:43 утра КНТ " в С#.
Ответ 4
Проблема с вышеприведенными подходами заключается в том, что основная причина, по которой вы используете строку формата, - это включить локализацию, а подходы, данные до сих пор, будут ломаться для любой страны или культуры, которые не хотят включать в себя окончательный 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;
}
Ответ 5
Это должно быть наиболее эффективным из всех этих параметров. Но слишком плохо они не могли работать в нижнем регистре в формате DateTime (tt напротив TT?).
public static string AmPm(this DateTime dt, bool lower = true)
{
return dt.Hour < 12
? (lower ? "am" : "AM")
: (lower ? "pm" : "PM");
}