0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-05-01
動作環境
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);
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?