2010-11-21 23 views
22

Tôi đang xây dựng một trang web lịch (ASP.NET MVC) ứng dụng (nghĩ rằng phiên bản đơn giản của outlook) và tôi muốn bắt đầu hỗ trợ các sự kiện lịch được định kỳ (hàng tháng, hàng năm, vv)Tôi có nên lưu trữ ngày hoặc quy tắc lặp lại trong cơ sở dữ liệu của mình khi tạo ứng dụng lịch không?

ngay bây giờ tôi đang lưu trữ ngày thực tế trong tôi nhưng tôi muốn tìm hiểu xem, với sự tái diễn, nó có ý nghĩa để tiếp tục lưu trữ ngày (với một số cutoff rõ ràng), hoặc tôi nên lưu trữ các tùy chọn lặp lại và tạo ra những ngày trên bay.

Điều đó khiến tôi nghĩ cách triển vọng, google mail, v.v. thực hiện điều này hoặc bất kỳ dịch vụ nào khác hỗ trợ các mục lịch định kỳ.

Có đề xuất nào về điều này không?

Trả lời

41

Phân tách dữ liệu của bạn thành hai phần: dữ liệu "chuẩn" (quy tắc lặp lại) và "phân phối" (ngày tạo; chỉ đọc ngoài một lần tạo lại). Nếu dữ liệu chuẩn thay đổi, hãy tạo lại dữ liệu "phân phối" tại thời điểm đó. Đối với các lần lặp lại vô hạn, hãy giữ một số trường hợp và tạo nhiều hơn nếu bạn chạy ra ngoài (ví dụ: nếu người dùng xem lịch của họ cho năm 2020).

Nếu bạn có tốc độ xử lý vô hạn, bạn chỉ cần dữ liệu chuẩn - nhưng thực tế, thực hiện tất cả xử lý ngày/giờ cho tất cả các quy tắc lặp lại trên mỗi lần xem trang có thể mất quá nhiều thời gian ... vì vậy bạn trao đổi một số lưu trữ (và độ phức tạp) để lưu tính toán lặp lại đó. Lưu trữ thường khá rẻ, so với tính toán cần thiết cho một số lượng lớn các sự kiện. Nếu bạn chỉ cần lưu trữ ngày của sự kiện, điều đó thực sự rất rẻ - bạn có thể dễ dàng sử dụng số nguyên 4 byte để biểu thị ngày và sau đó tạo ngày/giờ hoàn chỉnh từ đó, giả sử các lần lặp lại của bạn đều dựa trên ngày . Đối với các lần lặp lại dựa trên thời gian (ví dụ: "ba giờ một lần"), bạn có thể đầy đủ các phiên bản UTC - 8 byte sẽ đại diện cho độ phân giải đó thành độ phân giải khá tốt miễn là bạn có thể cần.

Bạn cần phải cẩn thận về việc duy trì hiệu lực mặc dù - nếu một cuộc họp định kỳ thay đổi nay, điều đó không thay đổi khi nó đã xảy ra trong quá khứ ... vì vậy bạn có thể muốn cũng có kinh điển dữ liệu chỉ đọc về thời điểm các sự kiện lặp lại thực sự xảy ra. Rõ ràng bạn sẽ không muốn điều đó để giữ cho quá khứ mãi mãi, vì vậy bạn có thể muốn "thu thập rác" sự kiện hơn một vài năm tuổi, tùy thuộc vào giới hạn lưu trữ của bạn.

Bạn cũng có thể cần thêm ghi chú và ngoại lệ (ví dụ: "cuộc họp không xảy ra hôm nay do ngày nghỉ lễ" hoặc "được chuyển đến 4 giờ chiều") trên cơ sở mỗi lần xuất hiện. Điều đó trở thành thực sự là thú vị khi bạn thay đổi sự lặp lại - nếu bạn thay đổi "mỗi Thứ Hai" thành "mỗi Thứ Ba", bạn có giữ ngoại lệ hay không? Làm thế nào để bạn thậm chí phù hợp với các ngoại lệ khi bạn thay đổi từ "mỗi ngày" sang "mỗi tuần"? Đây không phải là những câu hỏi trực tiếp về dung lượng lưu trữ - nhưng các quyết định lưu trữ sẽ ảnh hưởng đến việc dễ dàng thực hiện bất kỳ chính sách nào mà bạn quyết định.

3

Tôi chắc chắn sẽ sử dụng tùy chọn thứ hai của bạn. Sử dụng các tùy chọn lặp lại khác nhau, lưu trữ nó một cách riêng biệt và tính toán trên bay. Lưu trữ tất cả những ngày đó sẽ là một lượng dữ liệu không cần thiết.

Đây là câu trả lời hay để khen câu hỏi của bạn.
Data structure for storing recurring events?

Ngoài ra, như một lưu ý phụ. Tôi đã bắt đầu lưu trữ mọi thứ dưới dạng thời gian UTC để bạn có một đường cơ sở chung nếu bạn cần sử dụng nhiều múi giờ.

+0

nếu bạn lưu trữ một ngày riêng biệt cho mỗi lần lặp lại của mọi người dùng có sự lặp lại, nó có thể trở thành rất nhiều dữ liệu trong một vội vàng. –

+0

+1 ưu tiên lưu trữ lặp lại. Hãy nghĩ về trường hợp sử dụng khi người dùng di chuyển một trường hợp của sự kiện lặp lại: cô ấy có tùy chọn áp dụng di chuyển cho tất cả sự kiện, tất cả các sự kiện sau đó, chỉ sự kiện này, v.v. – Fuhrmanator

0

Tôi gặp phải sự cố tương tự trong ứng dụng web mà tôi đã thực hiện một vài năm trước (có thể có cách tốt hơn bây giờ :)). Tôi muốn bao gồm lịch trình có tất cả chức năng của các sự kiện định kỳ, thời gian xử lý, ngày, tuần, tháng, năm và trường hợp ngoại lệ, để tôi có thể có các quy tắc như:

1) Mỗi ​​ngày lúc 10 giờ sáng trừ thứ Tư

2) mỗi 2 giờ với tối đa là 4 lần lặp mỗi ngày

3) Thứ hai hàng tuần đầu tiên của Tháng

vv ..

Lưu trữ các ngày định kỳ/lần là có thể, nhưng không linh hoạt . Mỗi lần lặp lại sự kiện của bạn sẽ thay đổi khi "tối đa" sẽ là. Và bạn trông bao xa phía trước?

Cuối cùng, tôi đã viết một lớp lập lịch tùy chỉnh có thể đọc và ghi vào chuỗi. Đây là chuỗi được lưu trữ trong cơ sở dữ liệu và sau đó một hàm đơn giản có thể được gọi để tìm ra khi nào xảy ra tiếp theo.

+0

nhưng tôi cần nhiều hơn chỉ là lần xuất hiện tiếp theo – leora

+0

@ ooo, nhưng một lớp lịch trình được viết tốt có thể làm điều đó. Cho đến ngày hiện tại nó có thể tính toán lần xuất hiện tiếp theo, cái sau quảng cáo-vô hạn. Đầu vào cho hàm 'when()' của bạn phải là "now" và nó có thể trả về ngày xuất hiện tiếp theo. Cho rằng bạn có thể tính toán bao nhiêu tùy thích bằng cách cho ăn ngày được trả về 'khi()' hoặc bởi hàm đó cho bạn toàn bộ chuỗi. –

7

Tôi phải xây dựng một hệ thống làm việc với lịch biểu và chúng tôi đã làm cả hai. Dưới đây là những gì chúng tôi đã có

  • một bộ bảng theo dõi lịch biểu.
  • một bảng theo dõi các trường hợp trước đó của lịch biểu (khi chúng thực sự xảy ra)
  • một bảng theo dõi trường hợp cuối cùng và tiếp theo (khi mục tiếp theo sắp xảy ra dựa trên lần cuối) Bạn không cần bảng này, nhưng chúng tôi đã sử dụng bảng này, vì nếu không bạn sẽ liên tục tính toán nếu một mục sẽ xảy ra ngay bây giờ

Lập lịch biểu, mọi thứ có thể trở nên thực sự phức tạp bởi vì bạn phải nhớ rằng tại bất kỳ thời điểm nào trong thời gian, lịch trình có thể thay đổi.Ngoài ra, một mục có thể đến hạn khi ứng dụng của bạn không chạy và khi ứng dụng khởi động lại, bạn cần biết cách xác định các mục quá hạn.

Ngoài ra, chúng tôi đảm bảo rằng các bảng theo dõi lịch biểu thực tế chỉ đứng một mình. Lý do cho việc này là những bộ bảng phức tạp nhất trong hệ thống và chúng tôi muốn có thể tái sử dụng chúng để chúng có thể được sử dụng cho những thứ khác nhau cần lập lịch biểu. Chẳng hạn như gửi email quản trị, gửi thông báo và bảo trì máy chủ như dọn dẹp các tệp nhật ký.

1

Bạn cần lưu trữ một số trong số đó để đảm bảo. Người dùng có thể chỉnh sửa một trong các sự kiện, để người khác bị ảnh hưởng (bạn có thể đã gặp câu hỏi: "Bạn có muốn chỉnh sửa tất cả các sự kiện lặp lại hoặc chỉ sự kiện này không?" Trong một số lịch, ví dụ: Windows Mobile).

Bạn cũng có thể muốn lưu trữ các sự kiện trước đây và không xóa chúng khi người dùng xóa sự kiện lặp lại.

Nếu bạn lưu trữ tất cả những người khác hoặc tạo chúng là chi tiết triển khai. Tôi muốn tạo ra chúng, nếu có thể.

Trong mọi trường hợp, bạn sẽ muốn có một số ID của sự kiện định kỳ được lưu trữ với từng sự kiện, cộng với một số cờ cho bạn biết sự kiện đã được sửa đổi sau đó chưa. Hoặc trong cách tiếp cận phức tạp hơn, một cờ cho mỗi thuộc tính sự kiện kể, nếu đó là giá trị mặc định (từ sự kiện lặp lại) hoặc nếu nó được sửa đổi cho trường hợp cụ thể này. Bạn sẽ cần điều này khi người dùng quyết định chỉnh sửa sự kiện lặp lại.

7

Bạn sẽ cần phải xử lý các sự kiện và sự kiện riêng biệt.

EVENT WISE: Đối với các sự kiện, bạn sẽ cần phải lưu trữ quy tắc recurence (mà có thể là một rrule như theo quy định của rfc5545 mà còn là một bộ rõ ràng của ngày như rdate trong rfc5545) mà còn ngoại lệ (xem exdate của rfc5545 và có thể exrule như trong rfc2445). Bạn cũng sẽ cần phải theo dõi các thay đổi trong các quy tắc đó: Các thay đổi về tỷ lệ, cũ không có vấn đề gì khi chúng xảy ra trong tương lai và bị bỏ qua trong những ngày qua. Thay đổi trong rrule là khó khăn hơn như ảnh hưởng đến lần xuất hiện trước đó. Sở thích cá nhân của tôi là thêm một thuộc tính cụ thể cho rrule cũ và mới để chỉ định ngày bắt đầu và ngày kết thúc hợp lệ tương ứng của chúng.

nếu sự kiện có khoảng thời gian giới hạn (cho biết thuộc tính COUNT hoặc UNTIL), bạn nên lưu trữ bắt đầu và kết thúc trong bảng để cho phép truy vấn sự kiện dễ dàng hơn (đặc biệt là khi tìm kiếm lần xuất hiện bên ngoài cửa sổ thời gian được tính toán trước của bạn) bên dưới), nó có thể giúp giảm số lượng sự kiện mà tính toán sẽ được làm lại).

OCCURRENCES WISE: cho lần xuất hiện, bạn nên lưu trữ các trường hợp trong một cửa sổ được xác định trước xung quanh hiện tại (nói +/- 6 tháng hoặc 12 tháng và tính toán thường xuyên) và lưu hồ sơ này để cho phép tính lại nếu người dùng của bạn muốn để xem thêm trong tương lai (đối với các vấn đề về biểu diễn). bạn cũng nên xem xét tính toán chỉ mục (RECURRENCE-ID) để giúp tìm kiếm dễ dàng hơn về sự xuất hiện tiếp theo.

ít hơn trên back-end nhưng nhiều hơn trên front-end bạn cũng nên theo dõi các thay đổi tzid để hỏi người dùng nếu một sự kiện đã được lên lịch trên một tzid nhất định nếu nó có nghĩa là để ở trên múi giờ hiện tại của nó cần phải được cập nhật (nghĩ về một người ở đảo Samoa đã lên lịch họp vào thứ Sáu, ngày 30 tháng 12 năm 2011 trước khi quốc gia quyết định ngày này sẽ không tồn tại), tương tự như bạn có thể hỏi một sự kiện xảy ra trong thời gian tiết kiệm ánh sáng ban ngày có nghĩa là để "không bao giờ xảy ra" hay "xảy ra hai lần" (nhiều hơn về chủ đề này here)

Lưu ý: bạn có thể muốn xem xét hỗ trợ xa hơn những gì được định nghĩa trong rfc5545 về quy tắc recurence và cũng hỗ trợ thêm cho các quy tắc định kỳ tôn giáo (see USNO introduction to calendars hoặc in "Tính toán theo lịch" (Ấn bản thứ ba) từ E. Reingol và N. Dershowitz). Khi bạn hỏi về triển khai hiện tại, bạn có thể kiểm tra dễ dàng lược đồ cơ sở dữ liệu của sunbird (sqlite) hoặc của Apple open source Calendar and Contacts Server, một danh sách đầy đủ hơn về các dự án mã nguồn mở hiện có cho các máy chủ caldav (có thể là tập hợp con của những gì bạn đang sử dụng?). đang tìm kiếm) có sẵn here)

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