按日期和日期对对象数组进行排序时出现问题Javascript 中的时间 - 允许空值

发布于 2024-09-12 06:52:49 字数 1929 浏览 6 评论 0原文

我正在使用 Javascript 中的对象数组,需要按日期和时间对它们进行排序。设置如下:

地点

  • 标题
  • 日期(可选)
  • 时间(可选)

从概念上讲,该应用程序允许用户创建他们计划去的地点的列表。事件数组首先是手动排序的,用户可以选择向地点添加日期和时间值。我提供了一个按日期排序的按钮...日期为空的地点需要放置在列表的底部。

目前,它在不同浏览器上的表现有所不同。这是代码(假设我有 _places 数组和 _list 对象的句柄):

var _orderByDate = function (e) {
    YUE.preventDefault(e); // yui
    _places.sort(function (a, b) {
        var dateA = new Date(a.date),
            dateB = new Date(b.date);
        if ((!dateA === null) && (dateB === null)) return 0; //they're both null and equal
        else if ((dateA === null) && (dateB != null)) return -1; //move a downwards
        else if ((dateA != null) && (dateB === null)) return 1; //move b downwards
        else if ((dateA == dateB)) return (a.time > b.time) ? 1 : ((b.time > a.time) ? -1 : 0);
        else return (dateA > dateB) ? 1 : ((dateB > dateA) ? -1 : 0);
    });
    _list.updatePlaces(_places);
}

如果您认识上面的排序代码,那是因为我从另一篇文章中获得了基础知识,但我觉得这个值得拥有自己的,因为它处理日期...另一个只是处理空值和文本。

无论如何,在 Chrome 中,列表似乎按随机顺序排序,并且每次我执行 _orderByDate 函数时,它都会以不同的方式排序。在 Safari 中,第一次排序基本上是正确的,但会在列表顶部放置一个空日期位置。在 Firefox 中,什么也没有发生。

我是个初学者,而且我根本没有 CS 背景,所以我不擅长数组、日期、时间等基础知识……而且我的调试技能仅限于 Firebug 控制台。没有报告任何错误,所以我真的不知道出了什么问题。

需要注意的一件事是,如果我从函数中消除日期类型,以便将项目作为字符串进行排序,它可以正常工作...但这意味着 1/10/2011 将在 1/9/2011 之前排序,所以我认为我需要那里的日期类型。

有什么想法出了什么问题吗?有没有更聪明的方法来完成我想做的事情?

编辑:添加日志值

第一次排序(Chrome):

  • 08/01/2010
  • null
  • null
  • 08/03/2010
  • null
  • null
  • null
  • null
  • 7/01/2010
  • null
  • null
  • null

第二次排序(Chrome):

  • 08/01/2010
  • null
  • null
  • null
  • 07 2010
  • 8/03/2010
  • /01 /

I'm working with an array of objects in Javascript and need to sort them by date and time. Here's the setup:

place

  • title
  • date (optional)
  • time (optional)

Conceptually, the application allows users to create a list of places they're planning to go. The array of events is manually ordered at first, and users can optionally add date and time values to places. I'm providing an button to sort by date...places with null dates need to be placed at the bottom of the list.

Right now, it's behaving differently across browsers. Here's the code (assume I have a handle on the _places array and the _list object):

var _orderByDate = function (e) {
    YUE.preventDefault(e); // yui
    _places.sort(function (a, b) {
        var dateA = new Date(a.date),
            dateB = new Date(b.date);
        if ((!dateA === null) && (dateB === null)) return 0; //they're both null and equal
        else if ((dateA === null) && (dateB != null)) return -1; //move a downwards
        else if ((dateA != null) && (dateB === null)) return 1; //move b downwards
        else if ((dateA == dateB)) return (a.time > b.time) ? 1 : ((b.time > a.time) ? -1 : 0);
        else return (dateA > dateB) ? 1 : ((dateB > dateA) ? -1 : 0);
    });
    _list.updatePlaces(_places);
}

If you recognize the sort code above, that's because I got the basics from another post, but I felt this one deserved it's own since it deals with dates...the other was just dealing with null values and text.

Anyway, in Chrome, the list seems to sort in a random order, and it keeps sorting differently every time I execute the _orderByDate function. In Safari, it sorts mostly correct the first time, but puts one null date place at the top of the list. In Firefox, nothing happens at all.

I'm a bit of a beginner, and I don't have a CS background at all, so I'm not adept at the basics like arrays, dates, times etc...and my debugging skills are limited to the Firebug console. No errors are being reported, so I really have no idea what's going wrong.

One thing to note, if I eliminate the date type from the function so it sorts the items as strings, it works correctly...but that means 1/10/2011 would sort before 1/9/2011, so I think I need the date type in there.

Any ideas what's going wrong? Is there a smarter way to do what I'm trying to do?

EDIT: Adding log values

First sort (Chrome):

  • 08/01/2010
  • null
  • null
  • 08/03/2010
  • null
  • null
  • null
  • null
  • 7/01/2010
  • null
  • null
  • null

Second sort (Chrome):

  • 08/01/2010
  • null
  • null
  • null
  • 07/01/2010
  • null
  • null
  • null
  • null
  • null
  • 8/03/2010
  • null
  • null

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

也只是曾经 2024-09-19 06:52:49

[查看实际操作]

_places.sort(function (a, b) {
    var dateA = new Date(a.date + a.time), // merge the date & time
        dateB = new Date(b.date + b.time); // depending on the format
    if (!a.date && b.date) return 1;
    else if (a.date && !b.date) return -1;
    else if (dateA === dateB) return 0;
    else return (dateA > dateB) ? 1 : (dateB > dateA ? -1 : 0);
});

[See it in action]

_places.sort(function (a, b) {
    var dateA = new Date(a.date + a.time), // merge the date & time
        dateB = new Date(b.date + b.time); // depending on the format
    if (!a.date && b.date) return 1;
    else if (a.date && !b.date) return -1;
    else if (dateA === dateB) return 0;
    else return (dateA > dateB) ? 1 : (dateB > dateA ? -1 : 0);
});
夜巴黎 2024-09-19 06:52:49

如果您预处理数组,使其具有您要排序的列的数字表示形式,则可以大大简化排序算法。

例如,向表中添加一列,其中包含日期的 UTC 等效值。然后,您可以安全地按 UTC 属性对数组进行排序,但仍会显示字符串值。

for (var idx in _places)
    _places[idx].UTC = _places[idx].date ? new Date(_places[idx].date).UTC() : 0;

_places.sort(function(a, b)
{
    return a.UTC > b.UTC ? 1 : a.UTC < b.UTC ? -1 : 0;
});

如果您不想使用 Date 对象(1970 年之前的日期):

for (var idx in _places)
{
    var row = _places[idx];
    if (!row.date)
    {
        row.sortable = 0;
        continue;
    }
    var date = row.date.split('/');
    row.sortable = 10000 * parseInt(date[2]) + 100 * parseInt(date[0]) + parseInt(date[1]); // year, month, day
}

_places.sort(function(a, b)
{
    return a.sortable > b.sortable ? 1 : a.sortable < b.sortable ? -1 : 0;
});

当然,这假设您的日期始终具有相同的 M/D/Y 格式。

以下是上述算法的实际应用: http://jsfiddle.net/krNnn/

You can simplify the sorting algorithm by a great deal if you pre-process your array so that it will have a numeric representation of the column you want to sort by.

Add a column to the table that contains the UTC equivalent of the dates for instance. Then you can safely sort the array by the UTC property, but you will still display the string value.

for (var idx in _places)
    _places[idx].UTC = _places[idx].date ? new Date(_places[idx].date).UTC() : 0;

_places.sort(function(a, b)
{
    return a.UTC > b.UTC ? 1 : a.UTC < b.UTC ? -1 : 0;
});

If you don't want to use the Date object (pre-1970 dates):

for (var idx in _places)
{
    var row = _places[idx];
    if (!row.date)
    {
        row.sortable = 0;
        continue;
    }
    var date = row.date.split('/');
    row.sortable = 10000 * parseInt(date[2]) + 100 * parseInt(date[0]) + parseInt(date[1]); // year, month, day
}

_places.sort(function(a, b)
{
    return a.sortable > b.sortable ? 1 : a.sortable < b.sortable ? -1 : 0;
});

Of course this assumes that your dates will always have the same M/D/Y format.

Here's the above algorithm in action: http://jsfiddle.net/krNnn/

方觉久 2024-09-19 06:52:49

好吧,我们很忙,构建了一个相当复杂的功能,可以在所有浏览器上运行。我们的一些要求非常特殊(遥远的过去的日期,需要在底部对空日期进行排序,按时间进行子排序)。这是我们所做的:

         var _orderByDate = function(e) {
            YUE.preventDefault(e);
            _places.sort(function(a,b) {

                var Ay, Am, Ad, By, Bm, Bd;
                var Ah, Am, Bh, Bm;

                var dateA = a.date.split("/"); 
                if( !dateA.length || dateA.length != 3 || isNaN(dateA[0]) ||
                    isNaN(dateA[1]) || isNaN(dateA[2]) ) {
                    dateA = -1;
                } else {
                    Ay = parseInt(dateA[2]);
                    Am = parseInt(dateA[0]);
                    Ad = parseInt(dateA[1]);
                }

                var dateB = b.date.split("/"); 
                if( !dateB.length || dateB.length != 3 || isNaN(dateB[0]) || 
                    isNaN(dateB[1]) || isNaN(dateB[2]) ) {
                    dateB = -1;
                } else {
                    By = parseInt(dateB[2]);
                    Bm = parseInt(dateB[0]);
                    Bd = parseInt(dateB[1]);
                }

                // null checks
                if(dateA == -1 && dateB == -1) return 0;
                if(dateA == -1 && dateB != -1) return 1;
                if(dateA != -1 && dateB == -1) return -1;

                // year check
                if(Ay > By) return  1;
                if(By > Ay) return -1;

                // month check
                if(Am > Bm) return  1;
                if(Bm > Am) return -1;

                // day check
                if(Ad > Bd) return  1;
                if(Bd > Ad) return -1;


                var timeA = a.time.split(":");
                if( !timeA.length || timeA.length != 2 || isNaN(timeA[0]) ) {
                    timeA = -1;
                } else {
                    if( timeA[1].match(/am/) ) {
                        Ah = parseInt(timeA[0]);
                        Am = parseInt(timeA[1].match(/\d+/));
                    } else if( timeA[1].match(/pm/) ) {
                        Ah = parseInt((timeA[0] * 1) + 12);
                        Am = parseInt(timeA[1].match(/\d+/));
                    }
                }
                var timeB = b.time.split(":");
                if( !timeB.length || timeB.length != 2 || isNaN(timeB[0]) ) {
                    timeB = -1;
                } else {
                    if( timeB[1].match(/am/) ) {
                        Bh = parseInt(timeB[0]);
                        Bm = parseInt(timeB[1].match(/\d+/));
                    } else if( timeB[1].match(/pm/) ) {
                        Bh = parseInt((timeB[0] * 1) + 12);
                        Bm = parseInt(timeB[1].match(/\d+/));
                    }
                }

                // null time checks
                if(timeA == -1 && timeB == -1) return 0;
                if(timeA == -1 && timeB != -1) return 1;
                if(timeA != -1 && timeB == -1) return -1;

                // hour check
                if(Ah > Bh) return  1;
                if(Bh > Ah) return -1;

                // minute check
                if(Am > Bm) return  1;
                if(Bm > Am) return -1;

                return 0;
            } );

            _list.updatePlaces(_places);
        }

Ok, we got busy and built a rather complex function that works across all browsers. Some of the requirements we had were pretty special (dates in the distant past, need to sort null dates at the bottom, subsort by time). Here's what we did:

         var _orderByDate = function(e) {
            YUE.preventDefault(e);
            _places.sort(function(a,b) {

                var Ay, Am, Ad, By, Bm, Bd;
                var Ah, Am, Bh, Bm;

                var dateA = a.date.split("/"); 
                if( !dateA.length || dateA.length != 3 || isNaN(dateA[0]) ||
                    isNaN(dateA[1]) || isNaN(dateA[2]) ) {
                    dateA = -1;
                } else {
                    Ay = parseInt(dateA[2]);
                    Am = parseInt(dateA[0]);
                    Ad = parseInt(dateA[1]);
                }

                var dateB = b.date.split("/"); 
                if( !dateB.length || dateB.length != 3 || isNaN(dateB[0]) || 
                    isNaN(dateB[1]) || isNaN(dateB[2]) ) {
                    dateB = -1;
                } else {
                    By = parseInt(dateB[2]);
                    Bm = parseInt(dateB[0]);
                    Bd = parseInt(dateB[1]);
                }

                // null checks
                if(dateA == -1 && dateB == -1) return 0;
                if(dateA == -1 && dateB != -1) return 1;
                if(dateA != -1 && dateB == -1) return -1;

                // year check
                if(Ay > By) return  1;
                if(By > Ay) return -1;

                // month check
                if(Am > Bm) return  1;
                if(Bm > Am) return -1;

                // day check
                if(Ad > Bd) return  1;
                if(Bd > Ad) return -1;


                var timeA = a.time.split(":");
                if( !timeA.length || timeA.length != 2 || isNaN(timeA[0]) ) {
                    timeA = -1;
                } else {
                    if( timeA[1].match(/am/) ) {
                        Ah = parseInt(timeA[0]);
                        Am = parseInt(timeA[1].match(/\d+/));
                    } else if( timeA[1].match(/pm/) ) {
                        Ah = parseInt((timeA[0] * 1) + 12);
                        Am = parseInt(timeA[1].match(/\d+/));
                    }
                }
                var timeB = b.time.split(":");
                if( !timeB.length || timeB.length != 2 || isNaN(timeB[0]) ) {
                    timeB = -1;
                } else {
                    if( timeB[1].match(/am/) ) {
                        Bh = parseInt(timeB[0]);
                        Bm = parseInt(timeB[1].match(/\d+/));
                    } else if( timeB[1].match(/pm/) ) {
                        Bh = parseInt((timeB[0] * 1) + 12);
                        Bm = parseInt(timeB[1].match(/\d+/));
                    }
                }

                // null time checks
                if(timeA == -1 && timeB == -1) return 0;
                if(timeA == -1 && timeB != -1) return 1;
                if(timeA != -1 && timeB == -1) return -1;

                // hour check
                if(Ah > Bh) return  1;
                if(Bh > Ah) return -1;

                // minute check
                if(Am > Bm) return  1;
                if(Bm > Am) return -1;

                return 0;
            } );

            _list.updatePlaces(_places);
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文