.NET / SQL Server でユーザーの現地時間に電子メールを送信するにはどうすればよいですか?
-
09-06-2019 - |
質問
私は、ユーザーにとってローカルな時間に、毎正時に電子メールを送信する必要があるプログラムを作成しています。
異なるタイムゾーンに 2 人のユーザーがいるとします。ジョンはニューヨークにいて、フレッドはロサンゼルスにいます。サーバーはシカゴにあります。各ユーザーに現地時間の午後 6 時に電子メールを送信したい場合、サーバー時間の午後 7 時にジョンに電子メールを送信し、サーバー時間の午後 4 時にフレッドに電子メールを送信する必要があります。
.NET / SQL Server でこれに対する良いアプローチは何ですか?すべてのタイムゾーン情報を含む XML ファイルを見つけたので、それをデータベースにインポートするスクリプトを作成し、それに対してクエリを実行することを検討しています。
編集: 「t4znet.dll」を使用し、.NET 側ですべての比較を行いました。
解決
次の 2 つのオプションがあります。
- メールアクションの調整された時間を各ユーザーのデータベースに保存します。次に、サーバー時刻と保存されている時刻を比較するだけです。混乱と移植性の問題を避けるために、私はすべての時間を UTC で保存します。したがって、SERVER_UTC_TIME() == storageUtcTime のときにメールを送信します。
- 各メールアクションの現地時間をデータベースに保存し、その場で変換します。SERVER_UTC_TIME() == TO_UTC_TIME(storedLocalTime, userTimeZone) の場合にメールを送信します。
自分のアプリケーションにとって何が最も合理的であるかを判断する必要があります。たとえば、メール送信時間がすべてのユーザーに対して常に同じである場合は、オプション (2) を選択する方が合理的です。イベント時間がユーザー間で、さらにはユーザーごとに変わる可能性がある場合は、オプション (1) を選択すると開発とデバッグが容易になる可能性があります。いずれの場合でも、ユーザーのタイムゾーンを知る必要があります。
*これらの関数呼び出しは、T-SQL での呼び出しがわからないため、明らかに疑似ですが、存在するはずです。
他のヒント
私は PHP 開発者なので、PHP から知っていることを共有します。.NET にも同様のものが含まれると確信しています。
PHP では、サーバー上の異なる時間に電子メールを送信することを提案したように、サーバー時間のタイムゾーンの違いを取得できます。
ユーザーを追加するたびに、サーバー時間からの時間オフセット (サーバーのタイムゾーンが変更された場合はタイムゾーン) を保存します。
次に、更新を指定するときに、電子メールを送信する必要があるかどうかを確認するために 1 時間ごとに実行される自動タスク (LAMP ユーザーの場合は Cron) を実行します。送信するメールがなくなるまでこれを繰り返します。
この優れた記事でソリューションを補完できます。世界時計と TimeZoneInformation クラス」として、ローカル時間と受信者の時間を含む情報を含むファイルを送信する Web サービスを作成しました。私が行ったのは、この問題を処理できるようにこのクラスを変更することであり、必要なとおりに完璧に動作しました。
このクラスを使用して、「ユーザー」テーブルからユーザーのタイムゾーンを取得し、適切な時間を「計算」できると思います。私のコードは次のようになりました。
//Get correct destination time
DateTime thedate = DateTime.Now;
string destinationtimezone = null;
//Load the time zone where the file is going
TimeZoneInformation tzi = TimeZoneInformation.FromName(this.m_destinationtimezone);
//Calculate
destinationtimezone = tzi.FromUniversalTime(thedate.ToUniversalTime()).ToString();
このクラスには Windows Vista で「FromIndex(int Index)」関数がクラッシュするという問題がありますが、関数を使用する代わりにコードを変更できます。
public static TimeZoneInformation FromIndex(int index)
{
TimeZoneInformation[] zones = EnumZones();
for (int i = 0; i < zones.Length; ++i)
{
if (zones[i].Index == index)
return zones[i];
}
throw new ArgumentOutOfRangeException("index", index, "Unknown time zone index");
}
これを次のように変更できます。
public static TimeZoneInformation FromName(string name)
{
TimeZoneInformation[] zones = EnumZones();
foreach (TimeZoneInformation tzi in zones)
{
if (tzi.DisplayName.Equals(name))
return tzi;
}
throw new ArgumentOutOfRangeException("name", name, "Unknown time zone name");
}