2011-10-28 14 views
1

私は、次のコードを持っている:LINQ GROUPBYのDateTimeジレンマ

public IDictionary<string, int> GetCountByDate(DateTime fromDate, DateTime toDate) 
{ 
    var result = Database.Set<User>().Where(x => x.CreatedAt >= fromDate && x.CreatedAt <= toDate).GroupBy(x => new { x.CreatedAt.Year, x.CreatedAt.Month, x.CreatedAt.Day }).Select(x => new { Date = x.Key, Count = x.Count() }); 

    return result.ToDictionary(x => new DateTime(x.Date.Year, x.Date.Month, x.Date.Day).ToShortDateString(), x => x.Count); 
} 

このコードは完璧に動作しますが、問題は日時がデータベースにUTCとして格納されていることです。私がGroupByの操作をする瞬間、私はTimeの部分を失う。だから私は次のようにロカ時間に変換しようとした場合:

return result.ToDictionary(x => new DateTime(x.Date.Year, x.Date.Month, x.Date.Day).ToLocalTime().ToShortDateString(), x => x.Count); 

それは異なる時間に基づいているため、間違っています。列はDateTimeのままでなければなりません。

提案がありますか?

+0

あなたは何をしようとしているのかはっきりしていません... .NETを実行しているサーバーの現地時間に基づいてUTCに格納された日付をグループ化しようとしていますか?正直言って、それは良い考えであるとは思えません。 –

+0

私はデータベースにすべてをUTCとして保存しているので、日付別にグループ化されたユーザーの数を表示したいが、日付は現地時間でなければならない。理由は、ユーザーがESTの10/28午後9時に登録すると、GMTの午前2時10分の午前10時29分に実際にサインアップしたためです。現在のコードでは、その数は全員で29番目になります。私が達成しようとしているのは、東部時間のユーザが、そのユーザが28番目に帰属しているのを見るということです。何か意味がありますか? – Thomas

+0

しかし、それはサーバーのタイムゾーンではなく、*ユーザーの*タイムゾーンに関するものです。さまざまなタイムゾーンで動作させると、異なる人が異なる結果を得ることになり、どちらも素晴らしいとは言えません。人々がローカルタイム*にサインアップしたときに興味がある場合は、UTCではなく現地時間で保存する必要があります。 –

答えて

0

実際の挑戦のように聞こえるのは、2度翻訳する必要があるということです。まず、メソッドに入力しているローカルのDateTimeを取得します(ローカルの場合は質問のみが意味があります)。クエリの場合はUTCに変換する必要があります。しかし、サーバー上でグループ化する前にx.CreatedAtをローカルに変換する必要があります。換言すると、—です。これは扱いにくいですが、System.Data.Objects.SqlClientでSqlFunctionsライブラリを使用すると機能します。それはそれがどのように見えるかです。メッシーと私はどのようにパフォーマンスが良いのかわかりませんが、うまくいくはずです。その時点で

public IDictionary<string, int> GetCountByDate(DateTime fromDate, DateTime toDate) 
{ 
    DateTime utcFrom = fromDate.ToUniversalTime(); 
    DateTime utcTo = toDate.ToUniversalTime(); 
    int offset = (int)(fromDate - utcFrom).TotalHours; 
    var result = Database.Set<User>().Where(x => x.CreatedAt >= utcFrom && x.CreatedAt <= utcTo) 
     .GroupBy(x => new { 
      SqlFunctions.DateAdd("hh", offset, x.CreatedAt).Value.Year, 
      SqlFunctions.DateAdd("hh", offset, x.CreatedAt).Value.Month, 
      SqlFunctions.DateAdd("hh", offset, x.CreatedAt).Value.Day }) 
     .Select(x => new { Date = x.Key, Count = x.Count() }); 

    return result.ToDictionary(x => new DateTime(x.Date.Year, x.Date.Month, x.Date.Day).ToShortDateString(), x => x.Count); 
} 

、あなたの辞書オブジェクト内の日付値は、現地時間ですでにませんので、プレゼンテーションのためにそれらを変換する必要はありません。