Локализация диапазонов дат

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

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

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

  • Август - сентябрь 2009 г.
  • Август 2009
  • 1 августа - 9, 2009
  • 1 января - 3 марта 2009 г.
  • 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 используются с использованием этих форматов, поэтому я надеялся, что могут быть некоторые API Win32, которые это сделают, но поиск Google для "локализации диапазона дат Win32" ничего полезного не принес.

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

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

Ответ 1

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

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

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

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

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

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

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

[email protected]

и я был бы рад отправить их вам.

Ответ 2

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

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

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

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

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

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

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

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

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

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

Ответ 3

Ниже код обрабатывает 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));
}