Локализация диапазонов дат - PullRequest
12 голосов
/ 22 июля 2009

Кто-нибудь знает, как локализовать диапазоны дат с помощью C #?

В частности, я хочу создать «умные» диапазоны дат, чтобы исключить избыточную информацию.

Вот несколько примеров на американском английском

  1. Август - сентябрь 2009
  2. Август 2009
  3. 1 - 9 августа 2009 г.
  4. 1 января - 3 марта 2009 г.
  5. 6 декабря 2009 г. - 8 января 2010 г.

Форма, что я могу сказать. .NET Framework поддерживает локализацию дат, но не диапазоны дат.

Используя информацию в System.Globalization.DateTimeFormatInfo для локалей Windows, которые поддерживает CultureInfo, я смог выяснить (большую часть времени), как выполнять пункты № 1 и № 2. Пункт № 2 просто DateTime.ToString(DateTimeFormatInfo.YearMonthFormat). Используя YearMonthFormat я также смог вывести форматы для использования # 1 для большинства языков. Для немногих, кого я не мог, я просто дублировал год.

К сожалению, я не могу понять, как делать элементы №№3-5 с помощью .NET Framework. Форматы Outlook варьируются с использованием этих форматов, поэтому я надеялся, что могли бы быть некоторые Win32 API, которые бы это делали, но поиск в Google «локализация диапазона дат Win32» ничего полезного не дал.

Мне нравится улучшенное удобство использования, обеспечиваемое «форматированием интеллектуального диапазона», и я бы хотел, чтобы мои клиенты, не использующие английские версии Windows, получили те же преимущества.

Кто-нибудь знает, как сделать это в зависимости от культуры?

Ответы [ 3 ]

1 голос
/ 26 июля 2009

Я определил свои собственные форматы диапазонов для этого.

По большей части я извлек их из LongDatePattern. По возможности я проверял форматы по Календарю Google и / или носителям языка.

Я также сгенерировал 2 формата для временных диапазонов (в течение одного дня), один для одного и того же 12-часового периода, а другой для времен, выходящих за тот же 12-часовой период (для культур, использующих 24-часовой период, эти два формата одинаковы ). Они в основном основаны на FullDateTimePattern.

Во всех случаях я удалял названия дней (понедельник, вторник и т. Д.) Из всех форматов, где это было возможно.

Я хотел бы опубликовать их здесь, но кажется, что люди из Переполнения стека испытывают иррациональный страх перед HTML-таблицами, потому что они не допускают теги таблиц. Данные по сути являются гигантской таблицей. Я не заинтересован в том, чтобы моделировать таблицы с помощью CSS, поэтому я просто разместил таблицу на своем собственном сайте. Вы можете получить к нему доступ здесь, если вы заинтересованы:

http://www.transactor.com/misc/ranges.html

У меня есть несколько подробных заметок о том, как я получил много форматов, включая то, что было проверено, а что нет, если вы действительно заинтересованы. Если вы хотите эти заметки, просто отправьте электронное письмо по адресу:

contact@transactor.com

и я буду рад выслать их вам.

1 голос
/ 22 июля 2009

Хороший вопрос, и похоже, что в .NET Framework и других языках тоже не хватает. Я предполагаю, что представление результатов зависит от вашей заявки.

Outlook имеет очень хорошее понимание даты как ввод (как и календари Google), но я лично не видел эту форму выражения как вывод (например, отображаемый для пользователя).

Некоторые рекомендации:

  1. Придерживайтесь отображения даты начала и окончания и не беспокойтесь о избыточности
  2. Сверните свой .....: - (

Я бы предположил, что из вашего термина «локализация» вы планируете интернационализировать результаты, если в этом случае вам придется тяжело отрабатывать все случаи, это не похоже на информацию, сохраненную в большинстве типичных наборов данных интернационализации.

Сосредоточившись на английском из вашего примера, вы, кажется, имеете ряд правил, уже определенных в коде:

  1. Год всегда отображается.
  2. Месяц (хотя бы один из них) также всегда отображается.
  3. Дни не отображаются в случае 3, я бы хотел, чтобы это означало, что дата начала - 1-е, а конец - 31-е (например, каждый день месяца)
  4. День и месяц показываются, если начало / конец - разные месяцы.
  5. Год дополнительно отображается относительно даты начала, если эти две даты различаются по году.

Я знаю, что вышеизложенное относится только к английскому языку, но, на мой взгляд, это не выглядит слишком сложно, хотя и слишком много, чтобы писать в этом редакторе!

РЕДАКТИРОВАТЬ - Я знаю, что это не отвечает оригиналу - но если кто-то, использующий поисковую систему, найдет этот вопрос и захочет английскую версию ...

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(DateRange.Generate(2009, 08, 01, 2009, 09, 31));
        Console.WriteLine(DateRange.Generate(2009, 08, 01, 2009, 08, 31));
        Console.WriteLine(DateRange.Generate(2009, 08, 01, 2009, 08, 09));
        Console.WriteLine(DateRange.Generate(2009, 01, 01, 2009, 03, 03));
        Console.WriteLine(DateRange.Generate(2009, 12, 06, 2010, 01, 08));

        // Same dates
        Console.WriteLine(DateRange.Generate(2009, 08, 01, 2009, 08, 01));
    }
}

static class DateRange
{
    private static string[] Months = {
                                         "January", "February", "March", "April",
                                         "May", "June", "July", "August",
                                         "September", "October", "November", "December"
                                     };
    public static string Generate(
        int startYear, int startMonth, int startDay,
        int endYear, int endMonth, int endDay)
    {
        bool yearsSame = startYear == endYear;
        bool monthsSame = startMonth == endMonth;
        bool wholeMonths = (startDay == 1 && IsLastDay(endDay, endMonth));

        if ( monthsSame && yearsSame && startDay == endDay)
        {
            return string.Format("{0} {1}, {2}", startDay, Month(startMonth), startYear);
        }

        if (monthsSame)
        {
            if (yearsSame)
            {
                return wholeMonths
                           ? string.Format("{0} {1}", Month(startMonth), endYear)
                           : string.Format("{0} {1} - {2}, {3}", Month(endMonth), startDay, endDay, endYear);
            }
            return wholeMonths
                       ? string.Format("{0}, {1} - {2}, {3}",
                                       Month(startMonth), startYear,
                                       Month(endMonth), endYear)
                       : string.Format("{0} {1}, {2} - {3} {4}, {5}",
                                       Month(startMonth), startDay, startYear,
                                       Month(endMonth), endDay, endYear);
        }

        if (yearsSame)
        {
            return wholeMonths
                       ? string.Format("{0} - {1}, {2}", Month(startMonth), Month(endMonth), endYear)
                       : string.Format("{0} {1} - {2} {3}, {4}",
                                       Month(startMonth), startDay,
                                       Month(endMonth), endDay,
                                       endYear);
        }
        return wholeMonths
                   ? string.Format("{0}, {1} - {2}, {3}",
                                   Month(startMonth), startYear,
                                   Month(endMonth), endYear)
                   : string.Format("{0} {1}, {2} - {3} {4}, {5}",
                                   Month(startMonth), startDay, startYear,
                                   Month(endMonth), endDay, endYear);
    }

    private static string Month(int month)
    {
        return Months[month - 1];
    }

    public static bool IsLastDay(int day, int month)
    {
        switch (month+1)
        {
            case 2:
                // Not leap-year aware
                return (day == 28 || day == 29);
            case 1: case 3: case 5: case 7: case 8: case 10: case 12:
                return (day == 31);
            case 4: case 6: case 9: case 11:
                return (day == 30);
            default:
                return false;
        }
    }
}

Это дает тот же результат (почти, сентябрь становится моим в сентябре), что и оригинальный вопрос:

August - September, 2009
August 1 - 31, 2009
August 1 - 9, 2009
January 1 - March 3, 2009
December 6, 2009 - January 8, 2010
0 голосов
/ 22 июля 2009

Код ниже обрабатывает 4 и 5, если я правильно понял ваш код

public string GetDateRangeString(DateTime dt1, DateTime dt2)
{
   DateTimeFormatInfo info = new DateTimeFormatInfo();

   string format1;
   string format2;
   format2 = info.YearMonthPattern;
   format1 = dt1.Year == dt2.Year ? format1 = info.MonthDayPattern :
                                               format2;
   return string.Format("{0} - {1}", dt1.ToString(format1), dt2.ToString(format2));
}
...