如何在Javascript中使用Date作为史前日期?

Ogg*_*gge 75 javascript date

我正在开发一个JavaScript日期不够大的项目.

我想在同一时间轴上放置多个事件,其中一些有月和日,有些没有,所以只使用年份不是一个选项.我希望能够让登月和大爆炸在同一轴上.

如果我可以使用现有Date对象具有的功能,那将会有很大帮助.它只能追溯到27万年前,我需要一路回到大爆炸(13800,000,000年前).我不需要日期包含秒或毫秒.

如何扩展Date对象以包含此类日期的表示?

我试图为此找到库或本机函数,但没有运气.我也开始寻找我可以修改的Date对象的JavaScript实现,但我也没有运气.

更新:

我从remdevtec解决方案开始,但最终修改了很多.我希望日期以数字顺序排列,以便更轻松地对日期进行排序和排序.

所以我所做的是,如果年份在-100,000之前,我将毫秒值视为小时.这是我到目前为止所做的,它适用于我们的项目,但如果我有更多的时间,我会清理它并把它放在github上.

的jsfiddle

function BigDate(date){
    if(!date){
        this.original = new Date(); 
    }else if(date instanceof BigDate){
        this.original = date.original;
    }else{
        this.original = new Date(date);  
    }
    this.yearBreakpoint = -100000;
    this.breakPoint = Date.UTC(this.yearBreakpoint,0,0).valueOf();
    this.factor = 360000;//needed for our project to make extra space on our axis
}

BigDate.UTC = function (year, month, day, hour, minute, second, millisecond) {
    var temp = new BigDate();
    if(year < -temp.yearBreakpoint){
        temp.setUTCFullYear(year);
        return temp;
    }else{
        temp.original = Date.UTC(year,month,day,hour,minute,second,millisecond);
    }
    return temp.valueOf();
};

BigDate.now = function (){
    var temp = new BigDate();
    temp.original = Date.now();
    return temp.valueOf();
};

BigDate.parse = function (val){
    throw "not implemnted";
};

//custom functions

BigDate.prototype.getUTCDate = function () {
   if(this.valueOf() < this.breakPoint){
       return 0;
   }
   return this.original.getUTCDate();
};
BigDate.prototype.getUTCDay = function () {
   if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCDay();
};
BigDate.prototype.getUTCFullYear = function () {
    if(this.valueOf() < this.breakPoint){
        return (this.valueOf() - this.breakPoint) / this.factor;
    }
    return this.original.getUTCFullYear();
};
BigDate.prototype.getUTCHours = function () {
    if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCHours();
};
BigDate.prototype.getUTCMilliseconds = function () {
    if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCMilliseconds();
};
BigDate.prototype.getUTCMinutes = function () {
    if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCMinutes();
};
BigDate.prototype.getUTCMonth = function () {
    if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCMonth();
};
BigDate.prototype.getUTCSeconds = function () {
    if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCSeconds();
};

BigDate.prototype.setUTCDate = function (val) {
    if(val >= this.yearBreakpoint){
      return this.original.setUTCDate(val);
   }
};
BigDate.prototype.setUTCFullYear = function (val) {
    if(val < this.yearBreakpoint){
        this.original.setTime((parseInt(val) * this.factor) + this.breakPoint);
    }else{
        this.original.setUTCFullYear(val);
    }
    return this.valueOf();
};
BigDate.prototype.setUTCHours = function (val) {
    if(val >= this.yearBreakpoint){
      return this.original.setUTCHours(val);
    }
};
BigDate.prototype.setUTCMilliseconds = function (val) {
    if(val >= this.yearBreakpoint){
      return this.original.setUTCMilliseconds(val);
    }
};
BigDate.prototype.setUTCMinutes = function (val) {
    if(val >= this.yearBreakpoint){
        return this.original.setUTCMinutes(val);
    }
};
BigDate.prototype.setUTCMonth = function (val) {
    if(val >= this.yearBreakpoint){
      return   this.original.setUTCMonth(val);
    }
};
BigDate.prototype.setUTCSeconds = function (val) {
    if(val >= this.yearBreakpoint){
       return  this.original.setUTCSeconds(val);
    }
};

BigDate.prototype.setTime = function (val) {
    this.original.setTime(val);
    return this.valueOf();
};
BigDate.prototype.valueOf = function () {
    return this.original.valueOf();
};


BigDate.prototype.toDateString = function () {
    if(this.valueOf() < this.breakPoint){
        return "Jan 01 " + this.getUTCFullYear();
    }
    return this.original.toDateString();
};
BigDate.prototype.toISOString = function () {
    if(this.valueOf() < this.breakPoint){
        return this.getUTCFullYear() + "-01-01T00:00:00.000Z";
    }
    return this.original.toISOString();
};

BigDate.prototype.toJSON = function () {
    throw "not implemnted";
};
BigDate.prototype.toLocaleDateString = function () {
    throw "not implemnted";
};
BigDate.prototype.toLocaleTimeString = function () {
    throw "not implemnted";
};
BigDate.prototype.toLocaleString = function () {
    throw "not implemnted";
};
BigDate.prototype.toTimeString = function () {
    throw "not implemnted";
};
BigDate.prototype.toUTCString = function () {
    if(this.valueOf() < this.breakPoint){
        return "01 Jan "+ this.getFullYear() +" 00:00:00 GMT";
    }
    return this.original.toUTCString();
};




/**
 * Don't need no timezones
 */

BigDate.prototype.getDate = function () {
    return this.getUTCDate();
};
BigDate.prototype.getDay = function () {
    return this.getUTCDay();
};
BigDate.prototype.getFullYear = function () {
    return this.getUTCFullYear();
};
BigDate.prototype.getHours = function () {
    return this.getUTCHours();
};
BigDate.prototype.getMilliseconds = function() {
    return this.getUTCMilliseconds();
};
BigDate.prototype.getMinutes = function() { 
    return this.getUTCMinutes();
};
BigDate.prototype.getMonth = function () {
    return this.getUTCMonth();
};
BigDate.prototype.getSeconds = function () {
    return this.getUTCSeconds();
};
BigDate.prototype.getTimezoneOffset = function () {
    return 0;
};
BigDate.prototype.getTime = function () {
    return this.valueOf();
};

BigDate.prototype.setDate = function (val) {
    return this.setUTCDate(val);
};
BigDate.prototype.setFullYear = function (val) {
    return this.setUTCFullYear(val);
};
BigDate.prototype.setHours = function (val) {
    return this.setUTCHours(val);
};
BigDate.prototype.setMilliseconds = function (val) {
    return this.setUTCMilliseconds(val);
};
BigDate.prototype.setMinutes = function (val) {
    return this.setUTCMinutes(val);
};
BigDate.prototype.setMonth = function (val) {
    return this.setUTCMonth(val);
};
BigDate.prototype.setSeconds = function (val) {
    return this.setUTCSeconds(val);
};

BigDate.prototype.toString = function () {
    return this.toUTCString();
};
Run Code Online (Sandbox Code Playgroud)

rem*_*tec 81

我不需要日期包含秒或毫秒.

请注意,公历以400年的周期移动,因此周期为240,000年.因此,您可以使用Date您不想使用的60000毫秒表示,返回240000年周期(最多60000个这样的周期).这可以带你到大约公元前144亿年(就在大爆炸之前:)),分钟分辨率.

以下示例未考虑Date对象的所有功能.然而,通过进一步实施,我相信可以具有类似的功能.举例来说,一个BigDate,x是比另一个BigDate更大,y如果这两个日期ACx.original > y.original或者x.isAC()不过!y.isAC(),或者如果这两个日期是BC这样的,要么x.getFullYear() < y.getFullYear()x.getFullYear() === y.getFullYear() && x.original > y.original.

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);
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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..
Run Code Online (Sandbox Code Playgroud)

肉来了:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

一些演示(也可用于制作BigDate.prototype.toString()等):

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";
Run Code Online (Sandbox Code Playgroud)

结果内容将是: 4847996014 Jan 28 8: 21 BC

这是一个JSFiddle.

澄清

关于(合理的)设计评论,我知道BigDate上面提到的对象表现出糟糕的界面和设计.该对象仅作为使用秒和毫秒的未使用信息来满足该问题的示例.我希望这个例子有助于理解这种技术.

  • WTH不只是将偏移/因子存储在`BigDate`实例上,而不是将其隐藏在包装的`Date`对象中?你也应该暴露一个有用的构造函数,而不是让人们搞乱"因素". (12认同)
  • 我和@Bergi在一起.劫持秒和毫秒是不必要的,而且非常混乱.这是*非常糟糕的设计.-1. (2认同)
  • 我没有在编辑之前看到原版,但我认为你并没有真正将批评中的批评纳入你的修订版.我仍然看到偏移被填入"Date"对象的秒和毫秒字段中,特别是没有任何理由(无论如何都没有解释的原因).为什么不将偏移量放在"this.original"旁边的单独字段中?更不用说在不破坏`isAC()`的情况下无法表示未来的大日期.正如其他评论员所说,这是糟糕的设计,IMO目前的状态不应该是最高等级/接受的答案. (2认同)

Aar*_*ron 31

如果您只需要表示年份,那么一个简单的数字就足够了:它们最多可以代表+/- 9007199254740991.

您可以将其包装到自定义类中,以便为其提供日期函数.


Pet*_*ris 18

包裹日期

创建一个自己的类,通过添加一个长整数字段"year offset"来扩展Date类.

更新你想要用来应用今年抵消的所有方法 - 你可以保留几乎所有的东西,因为你没有触及处理时间和日期的复杂性; 也许它甚至足以让你改变构造函数和字符串格式化例程以包含"你的"年份.


Rah*_*thi 11

ECMAScript中说:

Date对象包含一个数字,表示一个毫秒内的特定时刻.这样的数字称为时间值.时间值也可以是NaN,表示Date对象不表示特定的时刻.

自UTC时间1970年1月1日起,时间以ECMAScript为单位,以毫秒为单位.在时间值中,忽略闰秒.假设每天恰好有86,400,000毫秒.ECMAScript数值可以表示从-9,007,199,254,740,992到9,007,199,254,740,992的所有整数; 此范围足以测量从UTC时间1970年1月1日起向前或向后约285,616年内的任何瞬间的毫秒精度.

ECMAScript日期对象支持的实际时间范围略小:相对于UTC时间1970年1月1日午夜测量的时间恰好为-100,000,000天到100,000,000天.这给UTC时间1970年1月1日的任何一方提供了8,640,000,000,000,000毫秒的范围.

1970年1月1日开始的午夜的确切时刻由值+0表示.

因此,您可以为日期创建自定义方法,您可以使用整数值作为年份.但实际上,日期的Ecmascript范围足以容纳所有实际日期.你试图实现的那个并没有真正的实际意义/含义,即使有人不确定它是否遵循 巴比伦的占星术