Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

Converting Days of the Week to and from a BitFlag

, 7 Oct 2011
Rate this:
Please Sign up or sign in to vote.
A utility class that lets you store a set of days of the week in a single int value

I thought I'd share this bit of code with you. It's basically a way of converting the System.DayOfWeek enum into a bitfield enum. Because I'm working on a transit database, I need a column that lets me store specific combinations of days, like Monday to Friday, or Saturday and Sunday. I'd like to translate those combinations into ints and back into combinations. So here's the utility class to do it:

public static class DaysOfWeekUtils
{
    #region Nested Enums
    [Flags]
    private enum DayOfWeekBitFlag
    {
        Sunday = 0x1,
        Monday = 0x2,
        Tuesday = 0x4,
        Wednesday = 0x8,
        Thursday = 0x10,
        Friday = 0x20,
        Saturday = 0x40
    }
    #endregion
 
    #region Private Fields
    private static Dictionary<DayOfWeekBitFlag, DayOfWeek> systemDayOfWeek;
    private static Dictionary<DayOfWeek, DayOfWeekBitFlag> bitFlagDayOfWeek;
    #endregion
 
    #region Constructors
    static DaysOfWeekUtils()
    {
        systemDayOfWeek = new Dictionary<DayOfWeekBitFlag, DayOfWeek>();
        systemDayOfWeek[DayOfWeekBitFlag.Sunday] = DayOfWeek.Sunday;
        systemDayOfWeek[DayOfWeekBitFlag.Monday] = DayOfWeek.Monday;
        systemDayOfWeek[DayOfWeekBitFlag.Tuesday] = DayOfWeek.Tuesday;
        systemDayOfWeek[DayOfWeekBitFlag.Wednesday] = DayOfWeek.Wednesday;
        systemDayOfWeek[DayOfWeekBitFlag.Thursday] = DayOfWeek.Thursday;
        systemDayOfWeek[DayOfWeekBitFlag.Friday] = DayOfWeek.Friday;
        systemDayOfWeek[DayOfWeekBitFlag.Saturday] = DayOfWeek.Saturday;
 
        bitFlagDayOfWeek = new Dictionary<DayOfWeek, DayOfWeekBitFlag>();
        bitFlagDayOfWeek[DayOfWeek.Sunday] = DayOfWeekBitFlag.Sunday;
        bitFlagDayOfWeek[DayOfWeek.Monday] = DayOfWeekBitFlag.Monday;
        bitFlagDayOfWeek[DayOfWeek.Tuesday] = DayOfWeekBitFlag.Tuesday;
        bitFlagDayOfWeek[DayOfWeek.Wednesday] = DayOfWeekBitFlag.Wednesday;
        bitFlagDayOfWeek[DayOfWeek.Thursday] = DayOfWeekBitFlag.Thursday;
        bitFlagDayOfWeek[DayOfWeek.Friday] = DayOfWeekBitFlag.Friday;
        bitFlagDayOfWeek[DayOfWeek.Saturday] = DayOfWeekBitFlag.Saturday;
 
        MondayToFridayCode = valueOf(DayOfWeek.Monday, DayOfWeek.Tuesday, 
            DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday);
    }
    #endregion
 
    #region Public Properties
    public static int MondayToFridayCode { get; private set; }
 
    public static IEnumerable<DayOfWeek> EachDayOfTheWeek
    {
        get
        {
            yield return DayOfWeek.Sunday;
            yield return DayOfWeek.Monday;
            yield return DayOfWeek.Tuesday;
            yield return DayOfWeek.Wednesday;
            yield return DayOfWeek.Thursday;
            yield return DayOfWeek.Friday;
            yield return DayOfWeek.Saturday;
        }
    }
 
    public static IEnumerable<DayOfWeek> MondayToFriday
    {
        get
        {
            return daysOfWeek(MondayToFridayCode);
        }
    }
    #endregion
 
    #region Public Methods
    public static IEnumerable<DayOfWeek> daysOfWeek(int val)
    {
        foreach (DayOfWeekBitFlag bitFlag in systemDayOfWeek.Keys)
            if ((val & (int)bitFlag) == (int)bitFlag)
                yield return systemDayOfWeek[bitFlag];
    }
 
    public static int valueOf(params DayOfWeek[] daysOfWeek)
    {
        return daysOfWeek.Distinct().Sum(dayOfWeek => (int)bitFlagDayOfWeek[dayOfWeek]);
    }
    #endregion
}

and here is its test class:

[TestClass]
public class DayOfWeekUtilsUnitTests
{
    #region Test Methods
    [TestMethod]
    public void testDaysOfTheWeek()
    {
        // Not doing this in a nested loop just
        // in order to see the structure clearly.
        foreach (DayOfWeek[] combination in combinations(7))
            testDaysOfWeek(combination);
 
        foreach (DayOfWeek[] combination in combinations(6))
            testDaysOfWeek(combination);
 
        foreach (DayOfWeek[] combination in combinations(5))
            testDaysOfWeek(combination);
 
        foreach (DayOfWeek[] combination in combinations(4))
            testDaysOfWeek(combination);
 
        foreach (DayOfWeek[] combination in combinations(3))
            testDaysOfWeek(combination);
 
        foreach (DayOfWeek[] combination in combinations(2))
            testDaysOfWeek(combination);
 
        foreach (DayOfWeek[] combination in combinations(1))
            testDaysOfWeek(combination);
    }
 
    private IEnumerable<DayOfWeek[]> combinations(int arrayLength)
    {
        if (arrayLength == 0)
            yield return new DayOfWeek[0];
        else
            foreach (DayOfWeek dayOfWeek in DaysOfWeekUtils.EachDayOfTheWeek)
                foreach (DayOfWeek[] combination in combinations(arrayLength - 1))
                    yield return combination.Concat(Enumerable.Repeat(dayOfWeek, 1)).ToArray();
    }
 
    [TestMethod]
    public void testDaysOfTheWeekUtilsProperty()
    {
        IEnumerable<DayOfWeek> daysOfTheWeek = DaysOfWeekUtils.EachDayOfTheWeek;
        Assert.AreEqual(daysOfTheWeek.Count(), 7);
        Assert.IsTrue(daysOfTheWeek.Contains(DayOfWeek.Sunday));
        Assert.IsTrue(daysOfTheWeek.Contains(DayOfWeek.Monday));
        Assert.IsTrue(daysOfTheWeek.Contains(DayOfWeek.Tuesday));
        Assert.IsTrue(daysOfTheWeek.Contains(DayOfWeek.Wednesday));
        Assert.IsTrue(daysOfTheWeek.Contains(DayOfWeek.Thursday));
        Assert.IsTrue(daysOfTheWeek.Contains(DayOfWeek.Friday));
        Assert.IsTrue(daysOfTheWeek.Contains(DayOfWeek.Saturday));
    }
 
    [TestMethod]
    public void testMondayToFriday()
    {
        IEnumerable<DayOfWeek> mondayToFriday = DaysOfWeekUtils.MondayToFriday;
        Assert.IsTrue(mondayToFriday.Count() == 5);
 
        Assert.IsTrue(mondayToFriday.Contains(DayOfWeek.Monday));
        Assert.IsTrue(mondayToFriday.Contains(DayOfWeek.Tuesday));
        Assert.IsTrue(mondayToFriday.Contains(DayOfWeek.Wednesday));
        Assert.IsTrue(mondayToFriday.Contains(DayOfWeek.Thursday));
        Assert.IsTrue(mondayToFriday.Contains(DayOfWeek.Friday));
    }
 
    [TestMethod]
    public void testNonExistentDays()
    {
        IEnumerable<DayOfWeek> noDays = DaysOfWeekUtils.daysOfWeek(256);
        Assert.AreEqual(noDays.Count(), 0);
    }
    #endregion
 
    #region Private Methods
    private void testDaysOfWeek(params DayOfWeek[] daysOfWeek)
    {
        int val = DaysOfWeekUtils.valueOf(daysOfWeek);
        IEnumerable<DayOfWeek> computedEnumeration = DaysOfWeekUtils.daysOfWeek(val);
        Assert.AreEqual(daysOfWeek.Distinct().Count(), computedEnumeration.Count());
        foreach (DayOfWeek dayOfWeek in computedEnumeration)
            Assert.IsTrue(daysOfWeek.Contains(dayOfWeek));
    }
    #endregion
}

To convert an int into an IEnumerable<DayOfWeek>, use the daysOfWeek() method; to go the other way, use the valueOf() method. I've included ModayToFriday and ModayToFridayCode shortcuts; feel free to add your own as and when the need arises.

Enjoy!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rob Lyndon

United Kingdom United Kingdom
Rob is an actor and a freelance developer, or a developer and a freelance actor, depending on which way the wind is blowing.

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.140905.1 | Last Updated 7 Oct 2011
Article Copyright 2011 by Rob Lyndon
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid