と聞かれましたが、ウェブアプリでタイムゾーンをどう扱うかという概念を掴むのに苦労しています。プロジェクトの進捗状況を追跡するシステムがあります。SQL Server データベースに ProjectStartDate DATE があります。(さらにいくつかのフィールドとテーブルがありますが、1 つに焦点を当てましょう)。
サーバーは米国のどこかにあります。私はオーストラリアに住んでいます。
呼び出しSELECT GETDATE()
は「2013-08-11 14:40:50.630」を返します 私のシステム時計は「2013-08-12 07:40」を示しています
私のデータベースでは、すべてのテーブルに「CreateDateTime」列があります。それをC#コード内に保存するときは、次を使用しますCreateDate = DateTime.UtcNow
UTCを使ったほうがいいと聞いたので、それを使っています。
しかし、ユーザーにカレンダー コントロールが表示され、プロジェクトの開始日を選択すると、ユーザーが選択した内容が保存されます。変換はありません...そして、私が言ったように、StartDate はデータベースの DATE 型です。
問題は、プロジェクトが今日開始された場合、サーバーがまだ昨日にあるため、フロント エンドで現在のプロジェクトが開始されていないと表示されることです。
日付を保存しているので、日付を保存する必要があると思います。しかし、どうにかしてユーザーのタイムゾーンを取得し、それを UI レベルで適用する必要があるのでしょうか?
私が見る問題は次のとおりです。
- ユーザーのタイムゾーンがわかりません。選択できるように何かを追加しますか?
- プロジェクトのステータスはストアド プロシージャで決定される場合がありますが、いつ変換を適用できますか? proc では、チェックを行い、StartDate <= DateTime.Now?
ほとんどの場合、EntityFramework と Linq を使用してデータを取得します。SQL の意味と .Net の意味の両方から、データを挿入および取得するための戦略が必要です。
これに基づいてユーザーにタイムゾーンを選択させるコードを追加しました。
public List<TimeZoneDto> GetTimeZones()
{
var zones = TimeZoneInfo.GetSystemTimeZones();
var result = zones.Select(tz => new TimeZoneDto
{
Id = tz.Id,
Description = tz.DisplayName
}).ToList();
return result;
}
それはその後、プロファイルに保持されます。
以下の回答でアドバイスされているように、すべての日付は UTC として保存されています。
データベースとの間、クライアントとの間で日付を処理する方法については、まだ混乱しています。レコードを保存する方法の例を次に示します。
public int SaveNonAvailibility(PersonNonAvailibilityDto n)
{
person_non_availibility o;
if (n.Id == 0)
{
o = new person_non_availibility
{
PersonId = n.PersonId,
Reason = n.Reason,
StartDate = n.StartDate,
EndDate = n.EndDate,
NonAvailibilityTypeId = n.NonAvailibilityTypeId,
CreateUser = _userId,
CreateDate = DateTime.UtcNow
};
_context.person_non_availibility.Add(o);
}
else
{
o = (from c in _context.person_non_availibility where c.Id == n.Id select c).FirstOrDefault();
o.StartDate = n.StartDate;
o.EndDate = n.EndDate;
o.Reason = n.Reason;
o.NonAvailibilityTypeId = n.NonAvailibilityTypeId;
o.LastUpdateDate = DateTime.UtcNow;
o.LastUpdateUser = _userId;
o.Deleted = n.Deleted ? DateTime.UtcNow : (DateTime?)null;
}
_context.SaveChanges();
return o.Id;
}
この方法は基本的に、人が仕事に出られないときに節約します。LastUpdateDate の保存方法に注意してください。また、「開始」日と「終了」日。これらの日付は、より「ビジネス」な日付です。
選択してから日付を確認すると、問題が発生します。この例では、NOW に基づいて個人の料金を取得しています。
public decimal CurrentRate
{
get
{
if (ResourceCosts != null)
{
var i = ResourceCosts.FirstOrDefault(t => DateTime.UtcNow <= (t.EndDate.HasValue ? t.EndDate.Value : DateTime.UtcNow) && DateTime.UtcNow >= t.StartDate);
if (i != null) return i.Cost;
return 0;
}
return 0;
}
}
ここで私がやりたいことは、現在の日付に基づいて、彼の料金を確認したいということです (彼の料金として、1 月 1 日から 1 月 15 日までは 100 ドル、16 日から 1 月 15 日までは 110 ドルになる可能性があります)。 1 月 31 日なので、今日適用可能なレートを探します (存在する場合)。これはタイム ゾーンを超えては機能しません。おそらく、ここで「DateTime.UTCNow」に基づいて日付操作を行う必要がありますか?
注、タイムゾーンを保存している上記のコードに基づいて、ユーザーのタイムゾーンがわかりました。ここでそれを何とか使用できますか?おそらく、ユーザーがログインすると、プロファイルから日付情報 (Zimezone 情報) を取得し、UTC 日付から時間を追加または削除することに基づいて、ユーザーの日時を返すグローバル共有関数を使用します...そしてそれを使用します私はどこで DateTime.UTCNow をやっていますか?
誰かが私を案内してくれることを願っています。