在JavaScript中修改数组对象中特定格式的日期。

huangapple go评论62阅读模式
英文:

Modify Dates in a certain format in an array of objects JavaScript

问题

我尝试修改对象中的日期,格式如下。基本上我想先将字符串日期转换为日期格式,然后尝试获取年份并确定它是今年上半年,即从2023.01.01到H1'2023还是今年下半年,即从2023.07.01到H2'2023,然后更新日期。非常感谢您的帮助。谢谢。

英文:

I am trying to modify the dates in an object in below format. Basically I want to first convert the string date into date format, then try to get the year and decide if it's 1st half of the year i.e. from 2023.01.01 to H1' 2023 or 2nd half of the year i.e. from 2023.07.01 to H2'2023 and then update the dates. Really appreciate your help Thanks

// Current Data set 

data = [{'description': 'halfyear', date: '2024.01.01'},
	{'description': 'halfyear', date: '2024.07.01'},
	{'description': 'halfyear', date: '2016.01.01'},
	{'description': 'halfyear', date: '2016.07.01'}
	]
// Expected Data 

data = [{'description': 'halfyear', date: 'H1\'2024'},
	{'description': 'halfyear', date: 'H2\'2024'},
	{'description': 'halfyear', date: 'H1\'2016'},
	{'description': 'halfyear', date: 'H2\'2016'}
	]

I have tried below but it doesn't seem to update correctly and override the values.

data.map(x=> {
 return x.formatted = 'H' + ' ' + new Date(x.date).getMonth() + 1 < 6 ? '1': '2' + new Date(x.date).getFullYear() + ''
})

Current Data- https://i.stack.imgur.com/jX9EK.png

Expected Result: https://i.stack.imgur.com/7tcMO.png

答案1

得分: 1

为了避免混淆括号和运算符优先级,我建议使用模板字符串。另外,您不需要在月份上添加 1,因为数学运算已经生效(< 6)。

const data = [
    { 'description': 'halfyear', date: '2024.01.01' },
    { 'description': 'halfyear', date: '2024.07.01' },
    { 'description': 'halfyear', date: '2016.01.01' },
    { 'description': 'halfyear', date: '2016.07.01' }
];

// 如果需要复制
const mapped = data.map(({date, description}) => {
    const [year, month] = date.split('.');
    return {
      description,
      date: `H${month < 6 ? 1 : 2}'${year}`
    };
});

// 如果需要原地转换
data.forEach(item => {
    const [year, month] = item.date.split('.');
    item.date = `H${month < 6 ? 1 : 2}'${year}`;
});

console.log(JSON.stringify(mapped));

console.log(JSON.stringify(data));
英文:

To avoid confusion while managing brackets and operator precedence I would recommend using template literals. Also you don't need to add to the month 1 since the math is already working (&lt; 6).

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const data = [
    { &#39;description&#39;: &#39;halfyear&#39;, date: &#39;2024.01.01&#39; },
    { &#39;description&#39;: &#39;halfyear&#39;, date: &#39;2024.07.01&#39; },
    { &#39;description&#39;: &#39;halfyear&#39;, date: &#39;2016.01.01&#39; },
    { &#39;description&#39;: &#39;halfyear&#39;, date: &#39;2016.07.01&#39; }
];

// if you need a copy
const mapped = data.map(({date, description}) =&gt; {
    const [year, month] = date.split(&#39;.&#39;);
    return {
      description,
      date: `H${month &lt; 6 ? 1 : 2}\&#39;${year}`
    };
});

// if you need in-place transform
data.forEach(item =&gt; {
    const [year, month] = item.date.split(&#39;.&#39;);
    item.date = `H${month &lt; 6 ? 1 : 2}\&#39;${year}`;
});

console.log(JSON.stringify(mapped));

console.log(JSON.stringify(data));

<!-- end snippet -->

答案2

得分: 0

解析字符串为Date,然后调用方法获取月份值的效率低下,因为月份值可以直接从字符串中获取。特别是在使用不受支持的字符串格式与内置的Date解析器一起使用时,这是有问题的。

要根据月份修改date属性的值,只需解析出月份,然后检查它是否小于7。例如:

let data = [
 { 'description': 'halfyear', date: '2024.01.01' },
 { 'description': 'halfyear', date: '2024.07.01' },
 { 'description': 'halfyear', date: '2016.01.01' },
 { 'description': 'halfyear', date: '2016.07.01' }
];

let data2 = data.map(obj => {
  let [y, m, d] = obj.date.split(/\D/);
  return { ...obj, date: `H${m < 7 ? 1 : 2}'${y}` };
});

console.log(data2)

PS
在原始问题中的以下表达式(仅查看包括条件表达式在内的部分)存在问题:

'H' + ' ' + new Date(x.date).getMonth() + 1 < 6 ? '1' : '2'

这被解释为:

('H' + ' ' + new Date(x.date).getMonth() + 1) < 6 ? '1' : '2'

如果new Date(x.date).getMonth()返回3,比较表达式将解析为:

'H 31' < 6

小于运算符<使用抽象关系算法。它首先将操作数转换为原始值,如果结果不是两个字符串,则将它们转换为数字。toNumber('H 31')返回NaN,所以现在你有:

NaN < 6

这个表达式计算为undefined(第4.d步),不管getMonth返回的值是什么(在0到11或NaN的范围内的整数):

undefined ? '1' : '2'

现在条件运算符? :的算法开始运行,并在左边调用toBoolean,它返回false:

false ? '1' : '2'

因此结果将始终为'2'。

要获取所需的结果,请添加一些括号以强制评估条件表达式,以防止受到周围代码的干扰:

'H' + ' ' + (new Date(x.date).getMonth() + 1 < 6 ? '1' : '2') + new Date(x.date).getFullYear() + ''

额外的一组括号可能有助于提高可读性:

'H' + ' ' + ((new Date(x.date).getMonth() + 1) < 6 ? '1' : '2') + new Date(x.date).getFullYear() + ''

当然,这假设new Date(x.date)返回一个有效的Date,在原始问题中,在某些实现中并非如此。 在JavaScript中修改数组对象中特定格式的日期。

英文:

It's inefficient to parse the string to a Date just to call a method to get back the month value when it's available directly from the string. It's particularly problematic to use the built–in Date parser with an unsupported string format.

To modify the value of the date property based on the month, just parse out the month and see if it's &lt; 7. E.g.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let data = [
 {&#39;description&#39;: &#39;halfyear&#39;, date: &#39;2024.01.01&#39;},
 {&#39;description&#39;: &#39;halfyear&#39;, date: &#39;2024.07.01&#39;},
 {&#39;description&#39;: &#39;halfyear&#39;, date: &#39;2016.01.01&#39;},
 {&#39;description&#39;: &#39;halfyear&#39;, date: &#39;2016.07.01&#39;}
];

let data2 = data.map(obj =&gt; {
  let [y, m, d] = obj.date.split(/\D/);
  return {...obj, date: `H${m &lt; 7? 1: 2}&#39;${y}`}; 
});

console.log(data2)

<!-- end snippet -->

PS

An issue in the OP is the following expression (looking at just the part up to and including the conditional expression):

&#39;H&#39; + &#39; &#39; + new Date(x.date).getMonth() + 1 &lt; 6 ? &#39;1&#39;: &#39;2&#39;

This is evaluated as:

(&#39;H&#39; + &#39; &#39; + new Date(x.date).getMonth() + 1) &lt; 6 ? &#39;1&#39;: &#39;2&#39;

If new Date(x.date).getMonth() returns say 3, the comparison expression resolves to:

(&#39;H&#39; + &#39; &#39; + 3 + 1) &lt; 6

which evaluates to (noting that the addition operator + is evaluated left to right and since the first expression is a string, each subsequent expression is converted to string before being added):

&#39;H 31&#39; &lt; 6

The less than operator &lt; uses the abstract relational algorithm. It first converts the operands to primitive and if the result isn't two strings, converts them to numbers. toNumber(&#39;H 31&#39;) returns NaN, so now you have:

NaN &lt; 6

This expression evaluates to undefined (step 4.d), regardless of the value returned by getMonth (an integer in the range 0 to 11 or NaN):

undefined ? &#39;1&#39; : &#39;2&#39;

Now the algorithm for the conditional operator ? : kicks in and calls toBoolean on the left hand side, which returns false:

false ? &#39;1&#39; : &#39;2&#39;

So the result will always be '2'.

To get the result you want, add some brackets to force the conditional expression to be evaluated without interference from the surrounding code:

&#39;H&#39; + &#39; &#39; + (new Date(x.date).getMonth() + 1 &lt; 6 ? &#39;1&#39;: &#39;2&#39;) + new Date(x.date).getFullYear() + &#39;&#39;

An extra set of brackets might help with readability:

&#39;H&#39; + &#39; &#39; + ((new Date(x.date).getMonth() + 1) &lt; 6 ? &#39;1&#39;: &#39;2&#39;) + new Date(x.date).getFullYear() + &#39;&#39;

This of course assumes that new Date(x.date) returns a valid Date, which, in the OP, it doesn't in some implementations. 在JavaScript中修改数组对象中特定格式的日期。

huangapple
  • 本文由 发表于 2023年6月16日 00:35:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76483783.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定