จัดรูปแบบวันที่ในเขตเวลาที่เฉพาะเจาะจง


177

ฉันใช้Moment.jsในการแยกวิเคราะห์และจัดรูปแบบวันที่ในแอปพลิเคชันเว็บของฉัน ในฐานะส่วนหนึ่งของวัตถุ JSON เซิร์ฟเวอร์แบ็คเอนด์ของฉันส่งวันที่เป็นจำนวนมิลลิวินาทีจาก UTC ยุค (Unix offset)

การแยกวันที่ในเขตเวลาที่ระบุนั้นเป็นเรื่องง่ายเพียงแค่ผนวกตัวระบุเขตเวลา RFC 822 ต่อท้ายสตริงก่อนที่จะแยกวิเคราะห์:

// response varies according to your timezone
const m1 = moment('3/11/2012 13:00').utc().format("MM/DD HH:mm")

// problem solved, always "03/11 17:00"
const m2 = moment('3/11/2012 13:00 -0400').utc().format("MM/DD HH:mm")

console.log({ m1, m2 })
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

แต่ฉันจะจัดรูปแบบวันที่ในเขตเวลาที่ระบุได้อย่างไร

ฉันต้องการผลลัพธ์ที่สอดคล้องโดยไม่คำนึงถึงเวลาปัจจุบันของเบราว์เซอร์ แต่ฉันไม่ต้องการแสดงวันที่ใน UTC


2
ช่วงเวลายังไม่สนับสนุนสิ่งนี้ แต่พวกเขากำลังทำงานอยู่ github.com/timrwood/moment/pull/671
Ben

5
มันควรจะได้ผล หากคุณผ่านช่วงเวลาที่มีสตริงเวลาที่มีออฟเซ็ตที่ต้องการคุณควรเก็บออฟเซ็ตนั้นไว้และแสดงเวลาท้องถิ่นตามที่กำหนดแทนที่จะปรับเป็นเวลาท้องถิ่นของเบราว์เซอร์โดยอัตโนมัติ หากฉันต้องการให้ปรับเวลาเบราว์เซอร์ท้องถิ่นฉันจะให้เวลา UTC แทนการให้ออฟเซ็ตใช้อย่างชัดเจน ฉันหมายถึง ... ฉันให้ออฟเซ็ตอย่างชัดเจนทำไมมันถึงทำให้กินและทำให้การแปลงเป็นเบราว์เซอร์ของคุณเอง การออกแบบแย่มาก
Triynko

@Triynko offsets อาจได้รับการปรับเวลาตามฤดูกาลดังนั้นจึงไม่สามารถทำงานได้อย่างที่คาดไว้
pinkpanther

1
สิ่งที่เกี่ยวข้องกับเรื่องนี้ฉันต้องการพิมพ์เวลาในรูปแบบเฉพาะเช่น15 มีนาคม 2018แต่ไม่พบสตริงรูปแบบที่จะทำ ทั่วไปไม่ทำงานเมื่อฉันใช้มันเหมือนDD MMM, YYYY moment.tz("2018-02-15T14:20:00.000+0530", "Asia/Bangkok").format("DD MMM, YYYY")ใครสามารถชี้ให้ฉันในเอกสารที่ฉันสามารถหากุญแจทั้งหมดสำหรับการจัดรูปแบบเวลาเมื่อใช้ API นี้
pRmdk

@PramodKumar เกิดอะไรขึ้น "15 Feb, 2018"ที่จะช่วยให้ คุณหมายถึงใช้สตริงรูปแบบDD MMMM, YYYYเพื่อรับ"15 February, 2018"หรือไม่
quietmint

คำตอบ:


248

เป็นแหลมออกในคำตอบจูงจมูกของ , .utcOffset()เป็นวิธีที่ต้องการ ณ ขณะ 2.9.0 ฟังก์ชั่นนี้ใช้การชดเชยจริงจาก UTC ไม่ใช่การชดเชยย้อนกลับ (เช่น -240 สำหรับนิวยอร์กระหว่าง DST) สตริงออฟเซ็ตเช่น "+0400" ทำงานเหมือนก่อนหน้านี้:

// always "2013-05-23 00:55"
moment(1369266934311).utcOffset(60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).utcOffset('+0100').format('YYYY-MM-DD HH:mm')

พี่.zone()เป็นหมาถูกเลิกใช้ใน Moment.js 2.9.0 เป็นที่ยอมรับสตริงที่มีตัวระบุเขตเวลา (เช่น "-0400" หรือ "-04: 00" เป็นเวลา 4 ชั่วโมง) หรือตัวเลขที่แสดงถึงจำนวนนาทีหลัง UTC (เช่น 240 สำหรับ New York ระหว่าง DST)

// always "2013-05-23 00:55"
moment(1369266934311).zone(-60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).zone('+0100').format('YYYY-MM-DD HH:mm')

หากต้องการทำงานกับเขตเวลาที่มีชื่อแทนการปรับค่าตัวเลขให้รวมMoment Timezoneและใช้.tz()แทน:

// determines the correct offset for America/Phoenix at the given moment
// always "2013-05-22 16:55"
moment(1369266934311).tz('America/Phoenix').format('YYYY-MM-DD HH:mm')

ฉันมีปัญหากับสิ่งนี้ผ่านข้อผิดพลาด "TypeError: Object 240 ไม่มีข้อผิดพลาด" format "" ฉันรู้ว่าโซนใช้ได้เฉพาะในฐานะ setter ในเวอร์ชั่น 2.1.0 และสูงกว่า Moment.js (และฉันใช้เวอร์ชันเก่ากว่า) ขอบคุณ!
Melinda Weathers

5
@ebi มันใช้เขตเวลาของเบราว์เซอร์เป็นค่าเริ่มต้นแล้ว ในการเข้าถึงการชดเชยเขตเวลาของเบราว์เซอร์ให้ใช้.zone()เป็นผู้ทะเยอทะยานซึ่งส่งคืนนาทีจาก UTC (เช่นส่งคืน 300 สำหรับนิวยอร์กในช่วงเวลามาตรฐาน)
quietmint

1
@EricCope ไม่เลย คุณสามารถใช้.tz("America/Phoenix")ถ้าคุณมีmomentjs.com/timezoneด้วยเช่นกัน ฉันได้อัปเดตคำตอบด้วยตัวอย่างแล้ว
quietmint

1
โปรดทราบว่าการใช้การชดเชยจะไม่ทำงานอย่างที่คาดไว้หากเขตเวลามีการชดเชยที่แตกต่างกันเนื่องจากการประหยัดเวลากลางวัน
pinkpanther

1
.utcOffset () จะจัดการเวลาตามฤดูกาลโดยอัตโนมัติหรือไม่ เช่นเมื่อฉันตั้ง UTC +1 CET ในฤดูหนาวมันจะเดิมพัน UTC +2 CEST ในช่วงเวลาออมแสงหรือไม่ สาเหตุนี้ทำให้ใช้งานได้หรือไม่!
haemse

61

ใช้เขตเวลา

moment(date).tz('Europe/Berlin').format(format)

ก่อนที่จะสามารถเข้าถึงเขตเวลาที่ต้องการคุณจะต้องโหลดอย่างนั้น (หรือใช้วิธีอื่นที่อธิบายไว้ที่นี่ )

moment.tz.add('Europe/Berlin|CET CEST CEMT|-10 -20 -30')

ฉันไม่คิดว่าจะมีสักครู่ tz เมื่อถามคำถาม แต่ฉันคิดว่านี่อาจเป็นวิธีที่จะไป ขณะนี้ฉันกำลังทำงานกับปัญหาที่คล้ายกันกับการประทับเวลาทั้งหมดที่จัดเก็บเป็น UTC ใน MySQL แต่จะดูได้ในโซนที่เฉพาะเจาะจงขึ้นอยู่กับการกำหนดค่าของผู้ใช้ไม่ใช่เขตเวลาของลูกค้า
nickdnk

47

คำตอบสองสามข้อได้กล่าวถึงเขตเวลาขณะนั้นเป็นวิธีที่จะไปกับเขตเวลาที่มีชื่อ ฉันแค่ต้องการอธิบายบางอย่างเกี่ยวกับห้องสมุดนี้ซึ่งค่อนข้างสับสนสำหรับฉัน มีความแตกต่างระหว่างสองคำสั่งนี้:

moment.tz(date, format, timezone)

moment(date, format).tz(timezone)

สมมติว่าไม่ได้ระบุเขตเวลาในวันที่ส่งผ่าน:

รหัสแรกใช้ในวันที่และสมมติว่าเขตเวลาเป็นรหัสที่ผ่านเข้ามารหัสที่สองจะใช้วันที่จะถือว่าเขตเวลาจากเบราว์เซอร์แล้วเปลี่ยนเวลาและเขตเวลาตามเขตเวลาที่ผ่านมา

ตัวอย่าง:

moment.tz('2018-07-17 19:00:00', 'YYYY-MM-DD HH:mm:ss', 'UTC').format() // "2018-07-17T19:00:00Z"

moment('2018-07-17 19:00:00', 'YYYY-MM-DD HH:mm:ss').tz('UTC').format() // "2018-07-18T00:00:00Z"

เขตเวลาของฉันคือ +5 จาก utc ดังนั้นในกรณีแรกจะไม่เปลี่ยนแปลงและจะกำหนดวันที่และเวลาให้มีเขตเวลา utc

ในกรณีที่สองจะถือว่าวันที่ผ่านไปอยู่ใน -5 จากนั้นเปลี่ยนเป็น UTC และนั่นเป็นเหตุผลว่าทำไมจึงแยกวันที่ "2018-07-18T00: 00: 00Z"

หมายเหตุ: พารามิเตอร์รูปแบบมีความสำคัญจริงๆ หากช่วงเวลาที่ถูกละเว้นอาจถอยกลับไปยังคลาสวันที่ซึ่งสามารถคาดเดาพฤติกรรมได้


สมมติว่ามีการระบุเขตเวลาในวันที่ผ่านไป:

ในกรณีนี้พวกเขาทั้งสองทำงานอย่างเท่าเทียมกัน


แม้ว่าตอนนี้ฉันเข้าใจว่าทำไมมันถึงใช้งานได้ฉันคิดว่านี่เป็นคุณสมบัติที่ค่อนข้างสับสนและคุ้มค่าที่จะอธิบาย


1
ขณะนี้ (... ). tz ไม่ใช่ฟังก์ชั่น
K - ความเป็นพิษใน SO กำลังเพิ่มขึ้น

5
คุณได้ติดตั้งเขตเวลาช่วงเวลาหรือไม่?
Nicola Pedretti

มีวิธีการแยกวิเคราะห์และช่วงเวลากลับโดยไม่จัดรูปแบบ? ตัวอย่างเช่นถ้าฉันต้องการจัดรูปแบบวิธีที่แตกต่างกันโดยไม่ต้องแยกวิเคราะห์มันอีกครั้ง
jEremyB

ขอบคุณสำหรับการชี้แจงสิ่งนี้ - ฉันมีปัญหาเมื่อตั้งค่าเขตเวลาที่แตกต่างจากเขตเวลาของเบราว์เซอร์ของผู้ใช้และนี่เป็นปัญหาที่แน่นอน
Robin Schaaf


8

ฉันมีปัญหาเดียวกันกับ Moment.js ฉันได้ติดตั้งเขตเวลาช่วงเวลาหนึ่ง แต่ปัญหาไม่ได้รับการแก้ไข จากนั้นฉันทำสิ่งที่นี่ถูกเปิดเผยตั้งเขตเวลาและทำงานได้อย่างมีเสน่ห์:

moment(new Date({your_date})).zone("+08:00")

ขอบคุณมาก!


16
คุณไม่ควรใช้ตัวnew Date()สร้าง ช่วงเวลาให้ทุกสิ่งที่คุณต้องการเพื่อแยกวิเคราะห์วันที่ ดูการแยกเอกสาร
quietmint

ใช่ แต่ถ้าฉันไม่ทำอย่างนั้นฉันก็ได้รับคำเตือนจาก Moment ว่ามันเลิกใช้แล้วอย่างนั้น
facundofarias

7
คำเตือนหมายถึงช่วงเวลาที่อยู่ในภายในลดลงกลับไปว่าสิ่งที่คุณกำลังทำ (ใช้new Date()ภายใน) แต่นี้เป็นที่ไม่สอดคล้องกันเบราว์เซอร์ คุณควรใช้รูปแบบที่คาดหวังเป็นอาร์กิวเมนต์ที่สองแทน ตัวอย่าง: moment("12-25-1995", "MM-DD-YYYY").
quietmint

4

เพิ่งจะมาถึงเรื่องนี้และเนื่องจากฉันมีปัญหาเดียวกันฉันจะโพสต์ผลลัพธ์ที่ฉันเกิดขึ้น

เมื่อแยกวิเคราะห์คุณสามารถอัปเดตออฟเซ็ต (เช่นฉันกำลังวิเคราะห์ข้อมูล (1.1.2014) และฉันต้องการเฉพาะวันที่ 1 มกราคม 2014 บน GMT + 1 ฉันจะได้รับ 31.12.2013 ฉันจึงชดเชยค่าแรก

moment(moment.utc('1.1.2014').format());

มีประโยชน์สำหรับฉันในการสนับสนุนข้ามเขตเวลา

B


-7

คุณสามารถลองสิ่งนี้

ที่นี่คุณสามารถรับวันที่ตามเขตเวลาของลูกค้า (เบราว์เซอร์)

moment(new Date().getTime()).zone(new Date().toString().match(/([-\+][0-9]+)\s/)[1]).format('YYYY-MM-DD HH:mm:ss')

regex ทำให้คุณได้รับค่าออฟเซ็ต

ไชโย !!


โดยปกติช่วงเวลาให้ทุกสิ่งที่คุณต้องการ คุณไม่จำเป็นต้องจับคู่สิ่งที่กำหนดเอง
Mahesh Samudra
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.