Làm thế nào để sử dụng Date trong Javascript cho các ngày tiền sử?


76

Tôi đang làm việc trong một dự án mà Ngày JavaScript không đủ lớn.

Tôi muốn đặt nhiều sự kiện trên cùng một trục thời gian, một số trong số đó có tháng và ngày và một số thì không, vì vậy chỉ sử dụng năm không phải là một tùy chọn. Tôi muốn có thể có mặt trăng hạ cánh và vụ nổ lớn trên cùng một trục.

Sẽ hữu ích rất nhiều nếu tôi có thể sử dụng chức năng mà đối tượng Date hiện có. Nó chỉ quay ngược lại 270.000 năm và tôi cần phải quay lại tất cả các con đường để quay trở lại vụ nổ lớn (13.800.000.000 năm trước). Tôi không cần ngày chứa giây hoặc mili giây.

Làm cách nào để mở rộng đối tượng Ngày để bao gồm đại diện cho những ngày như vậy?

Tôi đã cố gắng tìm thư viện hoặc các hàm gốc cho việc này nhưng không có may mắn. Tôi cũng bắt đầu tìm kiếm một triển khai JavaScript của đối tượng Date mà tôi có thể sửa đổi, nhưng tôi cũng không gặp may ở đây.

Cập nhật:

Tôi bắt đầu với giải pháp remdevtec nhưng cuối cùng đã sửa đổi nó khá nhiều. Tôi muốn các ngày đến theo thứ tự số để sắp xếp và sắp xếp các ngày dễ dàng hơn.

Vì vậy, những gì tôi đã làm là nếu năm trước -100.000 tôi coi giá trị mili giây là giờ. Đây là những gì tôi có cho đến nay và nó hoạt động trong dự án của chúng tôi, nhưng nếu tôi có thêm thời gian, tôi sẽ dọn dẹp nó và đưa nó lên github.

JSFiddle


14
Bạn nên nêu rõ yêu cầu của mình cho những ngày đó. Bạn có cần phải thực hiện số học ngày tháng chẳng hạn?
Aaron

23
Bạn có thực sự cần biết ngày và tháng nếu năm là 45.000.000 trước Công nguyên? Nếu vậy, bạn muốn sử dụng lịch nào (đặc biệt là vì ngày này có trước lịch ngày và lịch con người )? Tôi cho rằng có thể rất hay khi ghi lại sinh nhật của Dippy .
MT0

2
Hiểu rằng rất khó có khả năng hệ thống lịch sẽ vẫn như cũ trong 270000 năm nữa. Heck, thậm chí 1000 năm. Các phép tính ngày trong phạm vi rất dài có lẽ là vô ích. Điều này cũng áp dụng ngược thời gian: hệ thống lịch Gregorian hiện tại cuối cùng chỉ được sử dụng trên toàn cầu khoảng một trăm năm trước sau Thế chiến I.
Simba

13
Đại diện cho 270 nghìn năm = Vấn đề thế giới thứ nhất ở mức tốt nhất.
CodeAngry

1
Bạn đã cân nhắc sử dụng thang đo logarit chưa?
sampathsris

Câu trả lời:


81

Tôi không cần ngày chứa giây hoặc mili giây.

Lưu ý rằng lịch Gregory di chuyển theo chu kỳ 400 năm, do đó theo chu kỳ 240.000 năm. Do đó, bạn có thể lấy đại diện 60000 mili giây Datemà bạn không muốn sử dụng, quay ngược lại trong chu kỳ 240000 năm (lên đến 60000 chu kỳ như vậy). Điều này có thể đưa bạn đến khoảng năm 14,4 tỷ trước Công nguyên (ngay trước Big Bang :)), với độ phân giải chỉ vài phút.

Ví dụ sau không xem xét tất cả các chức năng của đối tượng Date. Tuy nhiên, với việc triển khai thêm, tôi tin rằng có thể có chức năng tương tự. Ví dụ: một BigDate,, xlớn hơn một BigDate khác y, nếu cả hai ngày đều ACx.original > y.originalhoặc nếu x.isAC()nhưng !y.isAC(), hoặc nếu cả hai ngày đều BCnhư vậy hoặc x.getFullYear() < y.getFullYear()hoặc x.getFullYear() === y.getFullYear() && x.original > y.original.

Sử dụng BigDate:

var time = new Date (
  [year /*range: 0-239999*/], 
  [month /*range: 0-11*/], 
  [day of month /*range: 1-31*/], 
  [hours /*range: 0-23*/], 
  [minutes /*range: 0-59*/], 
  [a factor of 240,000,000 years to go back (from the first parameter year) /*range: 0-59*/],
  [a factor of 240,000 years to go back (from the first parameter year) /*range: 0-999*/]); 
var bigDate = new BigDate(time);

HTML

<span id="years"></span>
<span id="months"></span>
<span id="date"></span>
<span id="hours"></span>
<span id="minutes"></span>
<span id="acbc"></span>

JAVASCRIPT

function BigDate (date) { this.original = date; }    

// set unchanged methods,
BigDate.prototype.getMinutes = function () { return this.original.getMinutes(); }
BigDate.prototype.getHours = function () { return this.original.getHours(); }
BigDate.prototype.getDate = function () { return this.original.getDate(); }
BigDate.prototype.getMonth = function () { return this.original.getMonth(); }

// implement other BigDate methods..

Và đây là thịt:

// now return non-negative year
BigDate.prototype.getFullYear = function () {  
  var ms = this.original.getSeconds() * 1000 + this.original.getMilliseconds();
  if (ms === 0) return this.original.getFullYear();
  else return (ms * 240000) - this.original.getFullYear();
}

// now add AC/BC method
BigDate.prototype.isAC = function () {
  var result = this.original.getSeconds() === 0 &&
    this.original.getMilliseconds() === 0;
  return result;
}

Một số bản demo (cũng có thể được sử dụng để sản xuất BigDate.prototype.toString(), v.v.):

var years = document.getElementById("years");
var months = document.getElementById("months");
var date = document.getElementById("date");
var hours = document.getElementById("hours");
var minutes = document.getElementById("minutes");
var acbc = document.getElementById("acbc");

// SET A TIME AND PRESENT IT
var time = new Date (2016, 1, 28, 8, 21, 20, 200); 
var bigDate = new BigDate(time);
var monthsName = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
years.innerHTML = bigDate.getFullYear();
months.innerHTML = monthsName[bigDate.getMonth()];    
date.innerHTML = bigDate.getDate();
hours.innerHTML = bigDate.getHours() + ":";
minutes.innerHTML = bigDate.getMinutes();
acbc.innerHTML = (bigDate.isAC()) ? "AC":"BC";

Nội dung kết quả sẽ là: 4847996014 Jan 28 8: 21 BC

Đây là một JSFiddle .

Làm rõ

Về các nhận xét thiết kế (hợp lý), tôi biết rằng BigDateđối tượng được trình bày ở trên có giao diện và thiết kế kém. Đối tượng chỉ được trình bày như một ví dụ về việc sử dụng thông tin chưa được sử dụng của giây và mili giây để thỏa mãn câu hỏi. Tôi hy vọng ví dụ này giúp hiểu kỹ thuật.


@Zach Ross-Clyne Cảm ơn bạn đã đề xuất chỉnh sửa. Tôi đã chỉnh sửa thêm một số, bao gồm cả đề xuất getSeconds()sử dụng của bạn .
remdevtec

12
WTH không chỉ lưu trữ offset / factor trên BigDateinstance, thay vì ẩn nó trong Dateđối tượng được bao bọc ? Ngoài ra, bạn nên để lộ một hàm tạo hữu ích, thay vì để mọi người xung quanh với các "yếu tố".
Bergi

2
Tôi với @Bergi. Việc chiếm đoạt giây và mili giây là không cần thiết và cực kỳ khó hiểu. Đó là thiết kế kém đáng kể . -1.
jpmc 26

2
Tôi không xem bản gốc trước khi chỉnh sửa nhưng tôi không nghĩ rằng bạn thực sự kết hợp những lời chỉ trích đã cho vào bản sửa đổi của mình. Tôi vẫn thấy phần bù được nhồi vào các trường Dategiây và mili giây của đối tượng mà không có lý do cụ thể nào (dù sao cũng không có lý do giải thích nào). Tại sao không đặt phần bù vào các trường riêng biệt cùng với this.original? Chưa kể các ngày lớn trong tương lai không thể được biểu diễn mà không bị phá vỡ isAC(). Như đã nói bởi các nhà bình luận khác, đây là thiết kế kém và IMO ở trạng thái hiện tại không phải là câu trả lời được đánh giá / chấp nhận cao nhất.
sv

@sv Câu hỏi không quan tâm đến việc đại diện cho các ngày lớn hơn trong tương lai. Về các ý kiến ​​khác của bạn, vui lòng xem phần làm rõ phụ lục trong bài đăng.
remdevtec

31

Nếu bạn chỉ cần đại diện cho năm, một Số đơn giản có thể là đủ: chúng có thể đại diện cho tới +/- 9007199254740991.

Bạn có thể bọc nó thành một lớp tùy chỉnh để cung cấp cho nó các hàm ngày tháng.


18

Kết thúc ngày

Tạo một lớp của riêng bạn mở rộng lớp Ngày bằng cách thêm một trường số nguyên dài "phần bù năm".

Cập nhật tất cả các phương pháp mà bạn muốn sử dụng để áp dụng bù trừ cho năm nay - bạn có thể để nguyên hầu hết mọi thứ, vì bạn không chạm vào sự phức tạp của thời gian và ngày xử lý; có thể nó thậm chí sẽ đủ để bạn thay đổi các hàm tạo và thói quen định dạng chuỗi để bao gồm năm "của bạn" trong đó.


11

Các ECMAScript nói:

Đối tượng Ngày chứa một Số chỉ một thời điểm cụ thể trong thời gian trong vòng một phần nghìn giây. Một Số như vậy được gọi là giá trị thời gian. Giá trị thời gian cũng có thể là NaN, chỉ ra rằng đối tượng Ngày không đại diện cho một khoảng thời gian cụ thể.

Thời gian được đo bằng ECMAScript tính bằng mili giây kể từ ngày 1 tháng 1 năm 1970 UTC. Trong thời gian giá trị giây nhuận bị bỏ qua. Giả định rằng có chính xác 86.400.000 mili giây mỗi ngày. Giá trị Số ECMAScript có thể đại diện cho tất cả các số nguyên từ –9,007,199,254,740,992 đến 9,007,199,254,740,992; phạm vi này đủ để đo thời gian với độ chính xác mili giây cho bất kỳ thời điểm nào trong vòng khoảng 285.616 năm, tiến hoặc lùi, kể từ ngày 1 tháng 1 năm 1970 UTC.

Phạm vi thời gian thực tế được hỗ trợ bởi các đối tượng Ngày của ECMAScript nhỏ hơn một chút: chính xác –100.000.000 ngày đến 100.000.000 ngày được đo tương ứng với nửa đêm đầu ngày 1 tháng 1 năm 1970 UTC. Điều này cung cấp phạm vi 8.640.000.000.000.000.000.000 mili giây cho mỗi bên của ngày 1 tháng 1 năm 1970 UTC.

Thời điểm chính xác của nửa đêm đầu ngày 1 tháng 1 năm 1970 UTC được biểu thị bằng giá trị +0.

Vì vậy, bạn có thể tạo một phương thức tùy chỉnh cho Ngày trong đó bạn có thể sử dụng giá trị số nguyên làm năm. Nhưng trên một lưu ý thực tế, phạm vi Ecmascript cho các ngày đủ tốt để chứa tất cả các ngày thực tế. Điều mà bạn đang cố gắng đạt được không có ý nghĩa / ý nghĩa thực tế thực sự vì thậm chí người ta không chắc nó có tuân theo chiêm tinh học Babylon hay không?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.