6

Tôi đang xây dựng ứng dụng trong mongodb và nodejs sẽ được sử dụng ở Ý. Múi giờ Ý là +02: 00. Điều này có nghĩa là nếu bất kỳ ai tiết kiệm một số dữ liệu vào lúc 01: sáng ngày 11 tháng 7 thì nó sẽ được lưu vào lúc 11:00 tối ngày 10 tháng 7 khi mongo lưu ngày tháng trong UTC. Chúng tôi cần hiển thị số lượng tx ngày khôn ngoan. Vì vậy, tôi đã nhóm theo truy vấn vào ngày. Nhưng nó cho thấy tx trong ngày hôm trước. Cần phải giải quyết vấn đề gì cho việc này.Tổng hợp theo múi giờ địa phương ở mongodb

> db.txs.insert({txid:"1",date : new Date("2015-07-11T01:00:00+02:00")}) 

> db.txs.insert({txid:"2",date : new Date("2015-07-11T05:00:00+02:00")}) 

> db.txs.insert({txid:"3",date : new Date("2015-07-10T21:00:00+02:00")}) 

> db.txs.find().pretty() 

{ 
     "_id" : ObjectId("55a0a55499c6740f3dfe14e4"), 
     "txid" : "1", 
     "date" : ISODate("2015-07-10T23:00:00Z") 
} 
{ 
     "_id" : ObjectId("55a0a55599c6740f3dfe14e5"), 
     "txid" : "2", 
     "date" : ISODate("2015-07-11T03:00:00Z") 
} 
{ 
     "_id" : ObjectId("55a0a55699c6740f3dfe14e6"), 
     "txid" : "3", 
     "date" : ISODate("2015-07-10T19:00:00Z") 
} 

> db.txs.aggregate([ 
    { $group:{ 
     _id: { 
      day:{$dayOfMonth:"$date"}, 
      month:{$month:"$date"}, 
      year:{$year:"$date"} 
     }, 
     count:{$sum:1} 
    }} 
    ]) 

    { "_id" : { "day" : 11, "month" : 7, "year" : 2015 }, "count" : 1 } 
    { "_id" : { "day" : 10, "month" : 7, "year" : 2015 }, "count" : 2 } 

Nó hiển thị 2 tx vào ngày 10 tháng 7 và ngày 1 tháng 11. Nhưng chúng ta cần hiển thị 2 tx trong 11 tháng 7 và 1 tx cho ngày 10 tháng 7.

Nó thực sự là 11 tháng 7 tại Ý khi

db.txs.insert({txid:"1",date : new Date("2015-07-11T01:00:00+02:00")}) 

đã diễn ra nhưng Mongo ngày lưu trữ như:

ISODate("2015-07-10T23:00:00Z") 
+1

Vậy nếu ai đó từ "New Zealand" muốn xem dữ liệu do người nào đó gửi trong "Ý" thì sao? Làm thế nào bạn nên lưu trữ thời gian sau đó? Đó là lý do tại sao ngày UTC được sử dụng vì chúng đại diện cho cùng một thời điểm cho mọi người. Chuyển đổi thành giờ địa phương trên "khách hàng" của bạn và cũng làm tương tự với "tham số truy vấn" lấy ngày địa phương và sau đó chuyển đổi chúng trở lại UTC. Bằng cách đó, các truy vấn và dữ liệu đều phù hợp trên toàn cầu. –

+0

@BlakesSeven Nhưng prob là nhóm đó bằng cách hiển thị bản ghi đó trong ngày trước đó. sao có thể truyền một số tham số như múi giờ trong khi tạo nhóm theo truy vấn trên mongo? –

Trả lời

3

Đối phó với các múi giờ là một "khách hàng" vấn đề, vì vậy bạn shoud sửa đổi "truy vấn" lần theo chênh lệch múi giờ để cho phép lựa chọn thời gian "cục bộ" trong giao diện người dùng và v.v. Điều tương tự cũng xảy ra đối với hiển thị giao diện người dùng, nơi các ngày được biểu diễn theo giờ địa phương.

Và điều tương tự cũng áp dụng cho nguyên tắc tập hợp của bạn. Chỉ cần điều chỉnh bằng bù trừ múi giờ. Appply ngày toán thay vì sử dụng các toán tử tập hợp date:

var tzOffset = 2; 

db.txs.aggregate([ 
    { "$group": { 
     "_id": { 
      "$subtract": [ 
       { "$add": [ 
        { "$subtract": [ "$date", new Date("1970-01-01") ] }, 
        tzOffset * 1000 * 60 * 60 
       ]}, 
       { "$mod": [ 
        { "$add": [ 
         { "$subtract": [ "$date", new Date("1970-01-01") ] }, 
         tzOffset * 1000 * 60 * 60 
        ]}, 
        1000 * 60 * 60 * 24 
       ]} 
      ] 
     }, 
     "count": { "$sum": 1 } 
    }} 
]).forEach(function(doc){ 
    printjson({ "_id": new Date(doc._id), "count": doc.count }) 
}); 

nào mang đến cho bạn:

{ "_id" : ISODate("2015-07-10T00:00:00Z"), "count" : 1 } 
{ "_id" : ISODate("2015-07-11T00:00:00Z"), "count" : 2 } 

Vì vậy, khi bạn $subtract ngày một BSON từ một kết quả là số mili giây kể từ unix thời đại. Chỉ cần sau đó điều chỉnh lại điều này bằng cách "thêm" "chênh lệch múi giờ" hoặc là sở hữu cho giờ chuyển tiếp hoặc âm cho phía sau, một lần nữa được chuyển đổi thành mili giây hợp lệ từ giá trị thời gian.

Làm tròn sau đó là một modulo đơn giản $mod để nhận phần còn lại từ "số mili giây trong một ngày" và loại bỏ điều đó để chỉ làm tròn ngày điều chỉnh thành ngày hiện tại.

Giá trị số kết quả ở đây có thể dễ dàng được đưa trở lại vào ngày vì tất cả đối tượng thư viện "Ngày" mất mili giây (hoặc giây) từ kỷ nguyên làm đối số hàm tạo.

Vì vậy, một lần nữa, đây là tất cả về việc sửa đổi phản hồi dữ liệu hiện tại từ "ngôn ngữ" của "khách hàng" của bạn chứ không phải về cách thức lưu trữ dữ liệu. Nếu bạn muốn địa phương thực sự trong ứng dụng của mình thì bạn áp dụng các sửa đổi cho các khoảng thời gian ở mọi nơi, giống như được trình bày ở trên.

-

Thực ra bạn chỉ có thể tạo ngày trong khung tổng hợp, với một chút toán ngày. Chỉ cần thêm ngày epoch trở lại ngày được chuyển đổi:

db.txs.aggregate([ 
    { "$group": { 
     "_id": { 
      "$add": [ 
       { "$subtract": [ 
        { "$add": [ 
         { "$subtract": [ "$date", new Date(0) ] }, 
         tzOffset * 1000 * 60 * 60 
        ]}, 
        { "$mod": [ 
         { "$add": [ 
          { "$subtract": [ "$date", new Date(0) ] }, 
          tzOffset * 1000 * 60 * 60 
         ]}, 
         1000 * 60 * 60 * 24 
        ]} 
       ]}, 
       new Date(0); 
      ] 
     }, 
     "count": { "$sum": 1 } 
    }} 
]) 
+0

@OmervanKloeten Sigh! Bạn cần phải suy nghĩ về điều này khó hơn và tôi không nói đến "chiết khấu DST" chút nào, mà đúng hơn là xem xét phạm vi ngày về sản lượng dự kiến ​​thì bạn "đối phó với nó" bằng cách chia nhỏ điều chỉnh từ dữ liệu miền địa phương của khách hàng (tức là những ngày này cho đến khi DST nghỉ và những ngày này sau) để điều chỉnh cho phù hợp. Lưu trữ nội dung cơ sở dữ liệu trong GMT "chỉ có ý nghĩa" vì nó là một điểm ổn định, nơi bạn có thể thực hiện tất cả các điều chỉnh từ. Đó là bài học ở đây. –

0

trong phiên bản mongo 3.6 múi giờ đã được thêm vào, mongo doc

biểu thức để trích xuất ngày một phần với múi giờ là

{ date: <dateExpression>, timezone: <tzExpression> } 

chúng ta có thể chỉ định các múi giờ hoặc bù đắp trong khi nhận được những phần ngày

đường ống

> db.txs.aggregate([ 
...  { $group:{ 
...   _id: { 
...    day: {$dayOfMonth: {date :"$date", timezone : "Europe/Rome"}}, // timezone 
...    month: {$month: {date : "$date", timezone : "+02:00"}}, //offset 
...    year: {$year: {date : "$date", timezone : "+02:00"}} //offset 
...   }, 
...   count:{$sum:1} 
...  }} 
... ]) 

kết quả

{ "_id" : { "day" : 10, "month" : 7, "year" : 2015 }, "count" : 1 } 
{ "_id" : { "day" : 11, "month" : 7, "year" : 2015 }, "count" : 2 } 
> 

danh sách timezone

Các vấn đề liên quan