从一组警报中获取第一个警报时间

时间:2017-04-20 18:50:27

标签: c# datetime time uwp data-management

我正在制作一个有多个(重新发生)闹钟的闹钟。

我使用安装了Microsoft IoT的raspberry pi和UWP(C#)作为布局和底层算法。

我遇到的问题是检索下一个闹钟时间。

伪代码:

Select nextAlarm()
   For all alarms a
       if (((a.time >= now.time AND a.repeatDay == now.DayOfWeek) 
          OR a.repeatDay > now.DayOfWeek) AND a.dateTime < currentAlarm.dateTime)
              currentAlarm = a;

然而,对于每个警报和函数a.repeatDay&gt;这将花费O(n)时间。 now.DayOfWeek不是一个简单的函数(如果当前日是星期三,下一个警报是星期一,则该函数不起作用)。

我要问的是如何以上述功能的工作方式(最好比O(n)更快)存储警报,或者如何存储所述问题解决的重复日期。

目前正在使用SQLite.net-pcl包

Alarm和RepeatDay类:

public class Alarm
{
    [PrimaryKey, AutoIncrement]
    public long Id { get; set; }

    [NotNull]
    public string Name { get; set; }

    [NotNull]
    public DateTime Time { get; set; }

    [NotNull]
    public int Repeat { get; set; }

    public Alarm(string name, DateTime time, RepeatWeek repeat)
    {
        this.Name = name;
        this.Time = time;
        this.Repeat = repeat;
    }

}

public class RepeatWeek
{
    int repeat = 0;
    public static implicit operator int(RepeatWeek w)
    {
        return w.repeat;
    }

    public void setDay(DayOfWeek w)
    {
        repeat |= 1 << (int)w;
    }

    public void removeDay(DayOfWeek w)
    {
        repeat &= ~(1 << (int)w);
    }

    public DayOfWeek getNext(DayOfWeek d, bool inclToday = false)
    {
        throw new NotImplementedException();
        return DayOfWeek.Monday; //Needs work
    }
}    

1 个答案:

答案 0 :(得分:1)

我已经尝试过实施GetNextDay。然后,实现Alarm.GetNext变得很简单,更简单的LINQ查询可以满足您的要求。我留下了一些让你实施,所以你可以说你做到了。

public class Alarm
{
    public long Id { get; set; }

    public string Name { get; set; }

    public DateTime Time { get; set; }

    public int Repeat { get; set; }

    public Alarm(string name, DateTime time, RepeatWeek repeat)
    {
        this.Name = name;
        this.Time = time;
        this.Repeat = repeat;
    }

    public DateTime GetNext()
    {
        var includeToday = true;
        if (DateTime.Now.TimeOfDay > Time.TimeOfDay)
        {
            includeToday = false;
        }

        var repeat = new RepeatWeek(Repeat);
        var nextDayOfWeek = repeat.GetNextDay(includeToday);
        return MergeDayOfWeekAndTime(nextDayOfWeek, Time);
    }

    private DateTime MergeDayOfWeekAndTime(DayOfWeek? nextDayOfWeek, DateTime Time)
    {
        //Left as exercise to the reader.
        throw new NotImplementedException();
    }
}

public class RepeatWeek
{
    int Repeat;

    public RepeatWeek(int repeat = 0)
    {
        Repeat = repeat;
    }

    public static implicit operator int(RepeatWeek w)
    {
        return w.Repeat;
    }

    public void setDay(DayOfWeek w)
    {
        Repeat |= 1 << (int)w;
    }

    public void removeDay(DayOfWeek w)
    {
        Repeat &= ~(1 << (int)w);
    }

    public static DayOfWeek FollowingDayOfWeek(DayOfWeek day)
    {
        if (day == DayOfWeek.Saturday)
        {
            return DayOfWeek.Sunday;
        }
        else
        {
            return day + 1;
        }
    }

    public DayOfWeek? GetNextDay(bool inclToday = false)
    {
        var inspect = DateTime.Now.DayOfWeek;
        if (!inclToday)
        {
            inspect = FollowingDayOfWeek(inspect);
        }

        for (int i = 0; i < 7; i++)
        {
            if ((Repeat & (1 << (int)inspect)) > 0) return inspect;
            inspect = FollowingDayOfWeek(inspect);
        }
        return null;
    }
}

[TestClass]
public class MyTestClass
{
    [TestMethod]
    public void GetNextDayOfWeek()
    {
        var repeat = new RepeatWeek();
        repeat.setDay(DayOfWeek.Monday);
        repeat.setDay(DayOfWeek.Tuesday);
        var expected = DayOfWeek.Monday;
        if (DateTime.Now.DayOfWeek == DayOfWeek.Monday)
        {
            expected = DayOfWeek.Tuesday;
        }

        var actual = repeat.GetNextDay();
        Assert.AreEqual(expected, actual);
    }

    [TestMethod]
    public void GetNextAlarm()
    {
        //Populate this yourself.
        var alarms = new List<Alarm>();
        var nextAlarm = alarms.Select(a => a.GetNext()).OrderBy(a => a.Ticks).FirstOrDefault();
    }
}