Chris Fulstow
Chris Fulstow

Reputation: 41872

Getting current culture day names in .NET

Is it possible to get the CurrentCulture's weekdays from DateTimeFormatInfo, but returning Monday as first day of the week instead of Sunday. And, if the current culture isn't English (i.e. the ISO code isn't "en") then leave it as default.

By default CultureInfo.CurrentCulture.DateTimeFormat.DayNames returns:

[0]: "Sunday"
[1]: "Monday"
[2]: "Tuesday"
[3]: "Wednesday"
[4]: "Thursday"
[5]: "Friday"
[6]: "Saturday" 

But I need:

[0]: "Monday"
[1]: "Tuesday"
[2]: "Wednesday"
[3]: "Thursday"
[4]: "Friday"
[5]: "Saturday" 
[6]: "Sunday"

Upvotes: 11

Views: 22885

Answers (9)

Nazar Frankiv
Nazar Frankiv

Reputation: 71

Another simple solution:

var dayNames = Thread.CurrentThread.CurrentCulture.DateTimeFormat.DayNames.ToList();

if (Culture.DateTimeFormat.FirstDayOfWeek == DayOfWeek.Monday)
{
    dayNames.Add(dayNames[0]);
    dayNames.RemoveAt(0);
}

Upvotes: 1

Gondil
Gondil

Reputation: 807

This should also work nice.

    public static List<String> Days
    {
        var abbDayNames = CultureInfo.CurrentCulture.DateTimeFormat.AbbreviatedDayNames;

        var days = new string[7];
        var firstDayOfWeek = (int)DayOfWeek.Monday;
        for (int i = 6; i>= 0; i--)
        {
            days[i] = abbDayNames[(firstDayOfWeek + i) % 7];
        }

        return new List<string>(days);
    }

Upvotes: 0

The Dag
The Dag

Reputation: 1841

If you are getting day names based on dates, it doesn't matter what day the week starts on; DateTimeFormat.DayNames identifies Sunday as 0, as does DateTime, no matter if weeks start on Thursday or what have you. :)

To get day name in English from a date:

string GetDayName(DateTime dt)
{
    return CultureInfo.InvariantCulture.DateTimeFormat.DayNames[(int)dt.DayOfWeek];
}

If for some reason you absolutely want to deal with the (magic value!) ints that underpin the DayOfWeek enumeration, just shift the index and take the modulus, hence mapping 0 => 6, 1 => 0, and so on:

string GetDayName(int dayIndex)
{
    return CultureInfo.InvariantCulture.DateTimeFormat.DayNames[(dayIndex + 6) % 7]; 
}

Upvotes: 2

cjbarth
cjbarth

Reputation: 4479

Since only one day is being moved, I solved this problem like this:

'the list is from Sunday to Saturday
'we need Monday to Sunday
'so add a Sunday on the end and then remove the first position
dayNames.AddRange(DateTimeFormatInfo.CurrentInfo.DayNames)
dayNames.Add(DateTimeFormatInfo.CurrentInfo.GetDayName(DayOfWeek.Sunday))
dayNames.RemoveAt(0)

Upvotes: 0

Nicolas Dorier
Nicolas Dorier

Reputation: 7465

DatetimeFormatInfo.GetDayName obviously, with a foreach on each DayOfWeek in the order you want. :) No hack, simple and effective

Upvotes: 3

Chris Fulstow
Chris Fulstow

Reputation: 41872

One more idea, inspired by Josh's answer, using a Queue instead of shifting the array.

var days = CultureInfo.CurrentCulture.DateTimeFormat.DayNames;
if (CultureInfo.CurrentCulture.TwoLetterISOLanguageName == "en")
{
    var q = new Queue<string>(days);
    q.Enqueue(q.Dequeue());
    days = q.ToArray();
}

Upvotes: 5

Josh
Josh

Reputation: 69262

I am posting this as a separate answer as it really has nothing to do with my other answer (which may be useful to someone else in the future in another context.)

As an alternative to codeka's solution, you can also do something like this (which would avoid having to hard code the en-us day names.)

string[] dayNamesNormal = culture.DateTimeFormat.DayNames;
string[] dayNamesShifted = Shift(dayNamesNormal, (int)DayOfWeek.Monday);

// you probably wanna add some error checking here.
// this method shifts array left by a specified number
// of positions, wrapping the shifted elements back to
// end of the array
private static T[] Shift<T>(T[] array, int positions) {
    T[] copy = new T[array.Length];
    Array.Copy(array, 0, copy, array.Length-positions, positions);
    Array.Copy(array, positions, copy, 0, array.Length-positions);
    return copy;
}

I meant to post this sooner but I am fighting a dying external hard drive...

Upvotes: 5

Josh
Josh

Reputation: 69262

You can Clone the current culture which gets a writable copy of the CultureInfo object. Then you can set the DateTimeFormat.FirstDayOfWeek to Monday.

CultureInfo current = CultureInfo.Current;
CultureInfo clone = (CultureInfo)current.Clone();

clone.DateTimeFormat.FirstDayOfWeek = DayOfWeek.Monday;

The above clone will now treat Monday as the first day of the week.

EDIT

After re-reading your question I don't think this will do what you're expecting. The DayNames will still return in the same order regardless of the FirstDayOfWeek setting.

But I'll leave this answer up as community wiki in case someone comes across this question in the future.

Upvotes: 7

Dean Harding
Dean Harding

Reputation: 72658

You can use custom cultures to create a new culture based off an existing one. To be honest, though, I'd say that's probably a bit heavy-handed. The "simplest" solution may just be something like:

public string[] GetDayNames()
{
    if (CultureInfo.CurrentCulture.Name.StartsWith("en-"))
    {
        return new [] { "Monday", "Tuesday", "Wednesday", "Thursday",
                        "Friday", "Saturday", "Sunday" };
    }
    else
    {
        return CultureInfo.CurrentCulture.DateTimeFormat.DayNames;
    }
}

Upvotes: 12

Related Questions