Help us understand the problem. What is going on with this article?

Visual Studio / WPF > イベント > DispatcherTimerを使ったAlarm機能の試作 > DateTime.Now.Subtract() | .TotalSeconds | .Add(new TimeSpan(0, 0, 1)) | .AddSeconds(1)

More than 3 years have passed since last update.
動作環境
Windows 7 Pro (32bit)
Microsoft Visual Studio 2017 Community
Sublime Text 2

DispatcherTimerを使ってAlarm機能を実装しようとした。

リンク

参考1: http://stackoverflow.com/questions/4946316/showing-difference-between-two-datetime-values-in-hours

v0.1

code

MainWindow.xaml
<Window x:Class="_170502_t0615_timer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:_170502_t0615_timer"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock Name="T_timer" FontSize="32" Text="00:00:00"/>
    </Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading; // for timer

namespace _170502_t0615_timer
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        DispatcherTimer myTimer;

        public MainWindow()
        {
            InitializeComponent();

            myTimer = new DispatcherTimer(DispatcherPriority.Normal);
            myTimer.Interval = new TimeSpan(0, 0, 1);
            myTimer.Tick += myTimer_Tick;
            myTimer.Start();
        }

        void myTimer_Tick(object sender, EventArgs e)
        {
            T_timer.Text = DateTime.Now.ToLongTimeString();

            var trigger = new DateTime(2017, 5, 2, 6, 27, 30);
            TimeSpan diff = DateTime.Now.Subtract(trigger);

            if (diff.Seconds == 0)
            {
                Console.WriteLine("Alarm");
            }
            Console.WriteLine("Tick");
        }
    }
}

結果

「出力」ウィンドウ。

...
Tick
Tick
Tick
Tick
Tick
Tick
Tick
Tick
Tick
Alarm
Tick
Alarm
Tick

Alarmが2回発行された。
バグっている。

v0.2

Alarm時の日時を表示するように変更。

MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading; // for timer

namespace _170502_t0615_timer
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        DispatcherTimer myTimer;

        public MainWindow()
        {
            InitializeComponent();

            myTimer = new DispatcherTimer(DispatcherPriority.Normal);
            myTimer.Interval = new TimeSpan(0, 0, 1);
            myTimer.Tick += myTimer_Tick;
            myTimer.Start();
        }

        void myTimer_Tick(object sender, EventArgs e)
        {
            T_timer.Text = DateTime.Now.ToLongTimeString();

            var trigger = new DateTime(2017, 5, 2, 6, 34, 30);
            TimeSpan diff = DateTime.Now.Subtract(trigger);

            if (diff.Seconds == 0)
            {
                Console.WriteLine("Alarm: on {0}", DateTime.Now.ToLongTimeString());
            }
            //Console.WriteLine("Tick");
        }
    }
}
Alarm: on 6:34:29
Alarm: on 6:34:30

Subtractしたときに1秒未満の誤差もdiff.Seconds==0ということになっているようだ。

c++ builder > TDateTime > SecondsBetween() > 秒未満の切捨てに注意をする
と同じような感じなのだろう。

v0.3

diff.TotalSeconds()を表示してみた。
1つのAlarm時刻だけだと少ないため、複数のAlarm時刻にした。

MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading; // for timer

namespace _170502_t0615_timer
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        DispatcherTimer myTimer;

        public MainWindow()
        {
            InitializeComponent();

            myTimer = new DispatcherTimer(DispatcherPriority.Normal);
            myTimer.Interval = new TimeSpan(0, 0, 1);
            myTimer.Tick += myTimer_Tick;
            myTimer.Start();
        }

        void myTimer_Tick(object sender, EventArgs e)
        {
            T_timer.Text = DateTime.Now.ToLongTimeString();

            DateTime [] triggers = {
                new DateTime(2017, 5, 2, 6, 44, 30),
                new DateTime(2017, 5, 2, 6, 44, 32),
                new DateTime(2017, 5, 2, 6, 44, 34),
            };
            TimeSpan diff;

            foreach(var trg in triggers)
            {
                diff = DateTime.Now.Subtract(trg);
                if (diff.Seconds == 0)
                {
                    //Console.WriteLine("Alarm: on {0}", DateTime.Now.ToLongTimeString());
                    Console.WriteLine("Alarm: on {0}", diff.TotalSeconds.ToString());
                }
            }


            //Console.WriteLine("Tick");
        }
    }
}
Alarm: on -0.9639294
Alarm: on 0.0581291
Alarm: on -0.9318132
Alarm: on 0.0782446
Alarm: on -0.9046972
Alarm: on 0.1103608

diff.TotalSecondsを0.1未満で切り捨てるのはだめのようだ。

v0.4 > 不等号使用案

http://stackoverflow.com/questions/10464743/is-there-a-better-way-to-set-an-alarm-clock-than-this
において不等号を使っている例があるのでそちらを使う。

MainWindowXaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading; // for timer

namespace _170502_t0615_timer
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        DispatcherTimer myTimer;

        public MainWindow()
        {
            InitializeComponent();

            myTimer = new DispatcherTimer(DispatcherPriority.Normal);
            myTimer.Interval = new TimeSpan(0, 0, 1);
            myTimer.Tick += myTimer_Tick;
            myTimer.Start();
        }

        void myTimer_Tick(object sender, EventArgs e)
        {
            T_timer.Text = DateTime.Now.ToLongTimeString();

            DateTime [] triggers = {
                new DateTime(2017, 5, 2, 6, 51, 30),
                new DateTime(2017, 5, 2, 6, 51, 32),
                new DateTime(2017, 5, 2, 6, 51, 34),
            };

            foreach(var startdt in triggers)
            {
                var enddt = startdt.Add(new TimeSpan(0, 0, 1));
                if (DateTime.Now >= startdt && DateTime.Now < enddt) 
                {
                    Console.WriteLine("Alarm: on {0}", DateTime.Now.ToLongTimeString());
                }
            }


            //Console.WriteLine("Tick");
        }
    }
}
Alarm: on 6:51:30
Alarm: on 6:51:32
Alarm: on 6:51:34

成功したが、もっと良い方法は他にもありそうだ。

v0.5 > AddSeconds()

https://msdn.microsoft.com/ja-jp/library/system.datetime(v=vs.110).aspx
過去の自分の記事を見ているとAddSeconds()というのが使えるようだ。

// var enddt = startdt.Add(new TimeSpan(0, 0, 1));
var enddt = startdt.AddSeconds(1);
7of9
セブンオブナインです。Unimatrix 01の第三付属物 9の7という識別番号です。Star trek Voyagerの好きなキャラクターです。まとめ記事は後日タイトルから内容がわからなくなるため、title検索で見つかるよう個々の記事にしてます。いわゆるBorg集合体の有名なセリフから「お前たち(の知識)を吸収する。抵抗は無意味だ」。Thanks in advance.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away