简体   繁体   English

在Javascript中拆分字符串的奇怪行为

[英]Strange behaviour with spliting a string in Javascript

I am trying to do something relatively simple. 我想做一些相对简单的事情。 I have a date in this format dd/MM/yyyy eg: 我有这种格式的日期dd / MM / yyyy例如:

var newDate = "‎11‎/‎06‎/‎2015";

And I want to convert it to a date. 我想将它转换为约会。

This code only works in Chrome and Firefox: 此代码仅适用于Chrome和Firefox:

new Date(newDate)

In IE11 I get Nan 在IE11中,我得到了Nan

So I am trying to do this: 所以我想这样做:

var parts = newDate.split("/");
var year = parts[2].trim();
var month = parts[1].trim();
var day = parts[0].trim();
var dt = new Date(Number(year), Number(month) - 1, Number(day));

Which should work, but I have encountered a very strange bug. 哪个应该有效,但我遇到了一个非常奇怪的错误。

If you try this code: 如果您尝试此代码:

 function myFunction() { var newDate = "‎11‎/‎06‎/‎2015"; var parts = newDate.split('/'); var year = parts[2].trim(); var a = year; var b = Number(year); var c = parseInt(year, 10); var d = parts; var n = a + "<br>" + b + "<br>" + c + "<br>" + d; document.getElementById("demo").innerHTML = n; } 
 <p>Click the button to see the parse error.</p> <button onclick="myFunction()">Try it</button> <p id="demo"></p> 

Then in IE it adds a mystery character and it prints out ý2015 and in chrome it prints out ?2015 . 然后在IE中它添加了一个神秘的角色,它打印出ý2015并在chrome中打印出来?2015

In fact the value of parts in IE is : ý11ý,ý06ý,ý2015 In Chrome: ?11?,?06?,?2015 事实上,IE中的部分价值是: ý11ý,ý06ý,ý2015在Chrome中: ?11?,?06?,?2015

I can't understand where these mystery characters come from! 我无法理解这些神秘人物的来源! My original string is just "‎11‎/‎06‎/‎2015" 我原来的字符串只是"‎11‎/‎06‎/‎2015"

There seems to be no way for be to do something so simple, such as parsing an integer from a simple string. 似乎没有办法做一些如此简单的事情,比如从简单的字符串中解析整数。

Fiddle doesn't show the hidden characters but I believe they are still there because Number("2015") results in NaN as you can see clearly here Any ideas? 小提琴没有显示隐藏的角色,但我相信他们仍然在那里,因为Number("2015")导致NaN因为你可以在这里清楚地看到任何想法?

UPDATE UPDATE

There are indeed hidden characters in the string, and after investigation I found out that they are created like this: 字符串中确实隐藏了字符,经过调查后我发现它们是这样创建的:

var date = new Date();
var dateToSave = date.toLocaleDateString();

but only in IE. 但仅限于IE。

In Chrome or Firefox the output doesn't contain the U+200E left-to-right mark but in IE it does! 在Chrome或Firefox中,输出不包含U+200E从左到右的标记,但在IE中它确实存在!

Removing toLocaleDateString() and replacing it with kendo.toString(selectedValue, "dd/MM/yyyy") fixed the problem. 删除toLocaleDateString()并用kendo.toString(selectedValue, "dd/MM/yyyy")替换它修复了问题。

For the record I also tried moment.js and the line: moment(selectedValue).format("DD/MM/YYYY") but for some reason in IE11 there was one hidden U+200E character at the very beginning of the result string. 为了记录我还尝试了moment.js和行: moment(selectedValue).format("DD/MM/YYYY")但由于某种原因在IE11中,在结果字符串的最开头有一个隐藏的U+200E字符。

I ran "‎11‎/‎06‎/‎2015".split('').map(function(s){return s.charCodeAt(0)}) (to get the Unicode values) in my console, and found something interesting: [8206, 49, 49, 8206, 47, 8206, 48, 54, 8206, 47, 8206, 50, 48, 49, 53] 我在我的控制台中运行了"‎11‎/‎06‎/‎2015".split('').map(function(s){return s.charCodeAt(0)}) (以获取Unicode值)有趣的东西: [8206, 49, 49, 8206, 47, 8206, 48, 54, 8206, 47, 8206, 50, 48, 49, 53]

You have a U+200E left-to-right mark in there. 你那里有一个U + 200E从左到右的标记 I don't know how it got there. 我不知道它是怎么到达那里的。

Remove it, and you'll be fine. 删除它,你会没事的。

Here, you can copy and paste the string from me: "11/06/2015" . 在这里,您可以复制并粘贴我的字符串: "11/06/2015"

Scimonster astutely figured out your problem, and dan explained how to strip non-ASCII characters, but there's an easier way: Just use a regular expression that matches digits only. Scimonster敏锐地发现了你的问题,并且dan解释了如何去除非ASCII字符,但是有一种更简单的方法:只使用仅匹配数字的正则表达式。 That way you don't have to use split or trim or strip anything out: 这样您就不必使用splittrim或剥离任何东西:

 function go() { var newDate = "‎11‎/‎06‎/‎2015"; var expr = /\\d+/g; var parts = newDate.match(expr); document.getElementById("result").innerHTML = "Parts: " + parts + "<br>Year: " + parts[0] + "<br>Month: " + parts[1] + "<br>Day: " + parts[2]; } 
 <button onclick="go()">Try me</button> <div id="result"/> 

This will work whether your string is "‎11‎/‎06‎/‎2015" or "11-6-2015" or junk11/06/2016junk . 无论您的字符串是"11-6-2015" "‎11‎/‎06‎/‎2015"还是"11-6-2015"junk11/06/2016junk

For older browsers, you need to write a function that will parse the string. 对于旧版浏览器,您需要编写一个将解析字符串的函数。

The following function will create a Date.fromISO method- if the browser can natively get the correct date from an ISO string, the native method is used.Some browsers got it partly right, but returned the wrong timezone, so just checking for NaN may not do. 以下函数将创建一个Date.fromISO方法 - 如果浏览器本身可以从ISO字符串中获取正确的日期,则使用本机方法。一些浏览器部分正确,但返回错误的时区,因此只需检查NaN可能不做。

(function(){
var D= new Date('2011-06-02T09:34:29+02:00');
if(!D || +D!== 1307000069000){
    Date.fromISO= function(s){
        var day, tz,
        rx=/^(\d{4}\-\d\d\-\d\d([tT ][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/,
        p= rx.exec(s) || [];
        if(p[1]){
            day= p[1].split(/\D/);
            for(var i= 0, L= day.length; i<L; i++){
                day[i]= parseInt(day[i], 10) || 0;
            };
            day[1]-= 1;
            day= new Date(Date.UTC.apply(Date, day));
            if(!day.getDate()) return NaN;
            if(p[5]){
                tz= (parseInt(p[5], 10)*60);
                if(p[6]) tz+= parseInt(p[6], 10);
                if(p[4]== '+') tz*= -1;
                if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
            }
            return day;
        }
        return NaN;
    }
}
else{
    Date.fromISO= function(s){
        return new Date(s);
    }
}
})()

Result will be: 结果将是:

var start_time = '2012-06-24T17:00:00-07:00';
var d =  Date.fromISO(start_time);
var month = d.getMonth();
var day = d.getDate();

alert(++month+' '+day); // returns months from 1-12

Below function worked for IE 8 and below. 以下功能适用于IE 8及以下版本。

// parse ISO format date like 2013-05-06T22:00:00.000Z
 function convertDateFromISO(s) {
 s = s.split(/\D/);
  return new Date(Date.UTC(s[0], --s[1]||'', s[2]||'', s[3]||'', s[4]||'', s[5]||'', s[6]||''))
  }

You can test like below: 你可以测试如下:

   var currentTime = new Date(convertDateFromISO('2013-05-06T22:00:00.000Z')).getTime();
   alert(currentTime);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM