我相信你正在使用的時區混淆特別是抵消一部分。
MongoDb總是以UTC時間保存日期。
所以,當你在MongoDB中查看日期時間時,你總是必須將偏離當地時區的因子考慮在內。
您將始終在當地時區發送日期。蒙戈C#驅動程序之前,堅持從本地更改時間UTC。
例如
當我保存CreatedOn = 2017-04-05 15:21:23.234
(當地時區(美國/芝加哥)),但 文檔當你看到在DB你會看到一些ISODate("2017-04-05T20:21:23.234Z")
即本地時間與UTC這是抵消的文件-5個小時。
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
指示驅動程序將時間從UTC轉換爲當地時間,然後將BSON返回到您的POCO。
下面是測試情況解釋的行爲。
代碼:
class Program
{
static void Main(string[] args)
{
var mongo = new MongoClient("mongodb://localhost:27017/test");
var db = mongo.GetDatabase("test");
db.DropCollection("students");
db.CreateCollection("students");
var collection = db.GetCollection<Student>("students");
var today = DateTime.Now; //2017-04-05 15:21:23.234
var yesterday = today.AddDays(-1);//2017-04-04 15:21:23.234
// Create 2 documents (yesterday & today)
collection.InsertMany(new[]
{
new Student{Description = "today", CreatedOn = today},
new Student{Description = "yesterday", CreatedOn = yesterday},
}
);
var filterBuilder1 = Builders<Student>.Filter;
var filter1 = filterBuilder1.Eq(x => x.CreatedOn, today);
List<Student> searchResult1 = collection.Find(filter1).ToList();
Console.Write(searchResult1.Count == 1);
var filterBuilder2 = Builders<Student>.Filter;
var filter2 = filterBuilder2.Eq(x => x.CreatedOn, yesterday);
List<Student> searchResult2 = collection.Find(filter2).ToList();
Console.Write(searchResult2.Count == 1);
}
}
public class Student
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
public DateTime CreatedOn { get; set; }
public string Description { get; set; }
}
收集:(通過蒙戈殼觀察時)
{
"_id" : ObjectId("58e559c76d3a9d2cb0449d84"),
"CreatedOn" : ISODate("2017-04-04T20:21:23.234Z"),
"Description" : "yesterday"
}
{
"_id" : ObjectId("58e559c76d3a9d2cb0449d85"),
"CreatedOn" : ISODate("2017-04-05T20:21:23.234Z"),
"Description" : "today"
}
更新:
"CreatedOn": ISODate("2017-03-31T20:27:12.914+05:00")
你的比較是不工作的原因是
var start = new DateTime(2017, 03, 31);
var end = new DateTime(2017, 03, 31);
這得到發送到服務器作爲$gte
比ISODate("2017-03-31T00:00:00.000+05:00")
和$lte
比ISODate("2017-03-31T00:00:00.000+05:00")
和它不發現上面的條目。
正確的方法來查詢today
日期將是
var start = new DateTime(2017, 03, 31);
var end = new DateTime(2017, 04, 01);
和更新您的過濾器
var filter = filterBuilder.Gte(x => x.CreatedOn, start) &
filterBuilder.Lt(x => x.CreatedOn, end);
所以,現在你的範圍查詢發送到服務器$gte
比ISODate("2017-03-31T00:00:00.000+05:00")
和$lt
比ISODate("2017-04-01T00:00:00.000+05:00")
你應該能夠找到今天的所有比賽。
更新2
更改數據庫的日期與時間部分時間設定存儲爲00:00:00。這將從db中刪除等式中的時間部分,並且您的舊範圍查詢將適用於所有情況。
更改保存方法使用
你可以回到舊的過濾器定義。
喜歡的東西
var start = new DateTime(2017, 03, 31);
var end = new DateTime(2017, 03, 31);
和更新您的過濾器
var filter = filterBuilder.Gte(x => x.CreatedOn, start) &
filterBuilder.Lte(x => x.CreatedOn, end);
所以,現在你的範圍查詢發送到服務器$gte
比ISODate("2017-03-31T00:00:00.000+05:00")
和$lte
比ISODate("2017-03-31T00:00:00.000+05:00")
,你應該能夠找到所有今天比賽。
更新3 - 僅限日期使用BsonDocument
進行比較。
這裏的想法是添加區偏移量是+5:00
服務器的UTC日期和變換計算的日期時間使用$dateToSting
運營商隨後在相同格式的輸入字符串日期比較字符串yyyy-MM-dd
格式。
這會在你的時區工作,但不會DST工作觀測時區。
蒙戈3.4版本
您可以使用$addFields
階段它增加了新的領域CreatedOnDate
同時保持所有現有的屬性和最後$project
從最終反應比較後丟棄CreatedOnDate
。
殼牌查詢:
{
"$addFields": {
"CreatedOnDate": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": {
"$add": ["$CreatedOn", 18000000]
}
}
}
}
}, {
"$match": {
"CreatedOnDate": {
"$gte": "2017-03-31",
"$lte": "2017-03-31"
}
}
}, {
"$project": {
"CreatedOnDate": 0
}
}
C#代碼:
var start = new DateTime(2017, 03, 31);
var end = new DateTime(2017, 03, 31);
var addFields = BsonDocument.Parse("{$addFields: { CreatedOnDate: { $dateToString: { format: '%Y-%m-%d', date: {$add: ['$CreatedOn', 18000000] }} }} }");
var match = new BsonDocument("CreatedOnDate", new BsonDocument("$gte", start.ToString("yyyy-MM-dd")).Add("$lte", end.ToString("yyyy-MM-dd")));
var project = new BsonDocument
{
{ "CreatedOnDate", 0 }
};
var pipeline = collection.Aggregate().AppendStage<BsonDocument>(addFields)
.Match(match)
.Project(project);
var list = pipeline.ToList();
List<Student> searchResult = list.Select(doc => BsonSerializer.Deserialize<Student>(doc)).ToList();
蒙戈版= 3.2
同上,但這個管道使用$project
所以你必須添加所有您希望保留在最終響應中的字段。
殼牌查詢:
{
"$project": {
"CreatedOn": 1,
"Description": 1,
"CreatedOnDate": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": {
"$add": ["$CreatedOn", 18000000]
}
}
}
}
}, {
"$match": {
"CreatedOnDate": {
"$gte": "2017-03-31",
"$lte": "2017-03-31"
}
}
}, {
"$project": {
"CreatedOn": 1,
"Description": 1
}
}
C#代碼:
var start = new DateTime(2017, 03, 31);
var end = new DateTime(2017, 03, 31);
var project1 = new BsonDocument
{
{ "CreatedOn", 1 },
{ "Description", 1 },
{ "CreatedOnDate", new BsonDocument("$dateToString", new BsonDocument("format", "%Y-%m-%d")
.Add("date", new BsonDocument("$add", new BsonArray(new object[] { "$CreatedOn", 5 * 60 * 60 * 1000 }))))
}
};
var match = new BsonDocument("CreatedOnDate", new BsonDocument("$gte", start.ToString("yyyy-MM-dd")).Add("$lte", end.ToString("yyyy-MM-dd")));
var project2 = new BsonDocument
{
{ "CreatedOn", 1 },
{ "Description", 1 }
};
var pipeline = collection.Aggregate()
.Project(project1)
.Match(match)
.Project(project2);
var list = pipeline.ToList();
List<Student> searchResult = list.Select(doc => BsonSerializer.Deserialize<Student>(doc)).ToList();
更新4 - 有儲蓄天燈工作日期只有比較。
蒙戈版= 3.6
一切都保持相同的期望$dateToString
將採取時區,而不是固定偏移量應該照顧日光節約變化考慮進去。
殼牌更新:
{
"$addFields": {
"CreatedOnDate": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": "$CreatedOn",
"timezone": "America/New_York"
}
}
}
}
C#更新:
var addFields = BsonDocument.Parse("{$addFields: { CreatedOnDate: { $dateToString: { format: '%Y-%m-%d', date: "$CreatedOn", "timezone": "America/New_York"} }} }");
你能從你的收藏,你期待你的當前日期查詢返回添加樣本文檔? – Veeram
我在數據庫中保存了DateTime.Now,看到我編輯的問題 –
Thanls @Veeram今天的例子我可以使用AddDays方法,但其他方法呢,我已經更新了我有的日期的過濾器。需要某種通用解決方案。 –