คุณแปลงวันที่เป็น JavaScript เป็น UTC ได้อย่างไร


590

สมมติว่าผู้ใช้เว็บไซต์ของคุณเข้าสู่ช่วงวันที่

2009-1-1 to 2009-1-3

คุณต้องส่งวันที่นี้ไปยังเซิร์ฟเวอร์เพื่อดำเนินการบางอย่าง แต่เซิร์ฟเวอร์คาดว่าวันที่และเวลาทั้งหมดจะอยู่ใน UTC

ตอนนี้สมมติว่าผู้ใช้อยู่ในอลาสกาหรือฮาวายหรือฟิจิ เนื่องจากอยู่ในเขตเวลาค่อนข้างแตกต่างจาก UTC ช่วงวันที่จึงต้องเปลี่ยนเป็นดังนี้:

2009-1-1T8:00:00 to 2009-1-4T7:59:59

การใช้ออบเจ็กต์วันที่ของ JavaScript คุณจะแปลงช่วงวันที่ "แปล" ครั้งแรกเป็นสิ่งที่เซิร์ฟเวอร์จะเข้าใจได้อย่างไร


10
เรียกคืนอีกครั้งเนื่องจากเป็นสิ่งที่ Google นิยมมากที่สุดสำหรับฉันและเบราว์เซอร์ที่ใหม่กว่ามีการสนับสนุนสตริงวันที่ UTC ในตัว
jcomeau_ictx

4
ฉันอัพเดตคำตอบที่ยอมรับเพื่อเน้นวิธี ECMAscript 5 toISOString () ใหม่ ดูstackoverflow.com/a/11957822/19112
dthrasher

5
ดังนั้นในปี 2015 ฉันต้องยุ่งกับ stringifying และการแยกวันที่? ไร้สาระ!
ชุดเครื่องมือ

2
แน่นอนคุณมี คุณไม่สามารถไว้ใจคนอื่นที่ทำงานให้คุณได้ :-P อย่างน้อยก็จนกว่าโลกจะหยุดใช้เขตเวลาและเริ่มรวมวันที่และเวลาเข้าด้วยกัน
Erenor Paz

4
"Stardates" โดยเฉพาะอย่างยิ่ง
Michael Daw

คำตอบ:


370

toISOString()วิธีการส่งกลับสตริงในรูปแบบการขยาย ISO ง่าย ( ISO 8601 ) ซึ่งมักจะเป็น 24 หรือ 27 ตัวอักษร ( YYYY-MM-DDTHH:mm:ss.sssZหรือ±YYYYYY-MM-DDTHH:mm:ss.sssZตามลำดับ) เขตเวลาเป็นออฟเซ็ต UTC ศูนย์เสมอซึ่งแสดงโดยคำต่อท้าย " Z"

ที่มา: MDN เอกสารเว็บ

รูปแบบที่คุณต้องการสร้างด้วย.toISOString()วิธีการ สำหรับเบราว์เซอร์รุ่นเก่า (เช่น 8 และรุ่นต่ำกว่า) ซึ่งไม่สนับสนุนวิธีนี้ในแบบดั้งเดิม shim สามารถพบได้ที่นี่ :

สิ่งนี้จะทำให้คุณสามารถทำสิ่งที่คุณต้องการ:

var isoDate = new Date('yourdatehere').toISOString();

สำหรับการทำงานในเขตเวลาเขตเวลาmoment.js และ moment.js เขตเวลาเป็นเครื่องมือที่ประเมินค่ามิได้จริง ๆ ... โดยเฉพาะอย่างยิ่งสำหรับการนำเขตเวลาระหว่างไคลเอนต์และเซิร์ฟเวอร์จาวาสคริปต์


81
จริงๆแล้วสิ่งนี้จะแปลงอ็อบเจกต์วันที่เป็นสตริงจะไม่สามารถดำเนินการกับวันที่ได้อีกต่อไป
orszaczky

2
@TheRebel กรณีการใช้งานที่กำหนดคือเขาต้องส่งเซิร์ฟเวอร์ที่จัดรูปแบบสตริง
Will Stern

28
@ Will คุณพูดถูก แต่ฉันก็ถือว่าผู้ชมส่วนใหญ่ที่นี่ - ฉันมาถึงที่นี่ตามชื่อค้นหาวันที่ JS ทั่วไปสำหรับการแปลง UTC ดังนั้นฉันคิดว่ามันมีประโยชน์ที่จะพูดถึงที่นี่ :)
orszaczky

4
ระวังเมื่อใช้วิธีนี้! มันไม่ได้สร้างวันที่ UTC - มันจัดรูปแบบข้อมูลวันที่ที่มีอยู่ตามที่เป็นในรูปแบบ UTC และให้เขตเวลา "Z" นี่เป็นความผิด 99% ของเวลา! คุณต้องแปลงวันที่เป็นเขตเวลา GMT ก่อนที่จะใช้วิธีนี้!
user1944491

5
@ user1944491 ฉันไม่คิดว่ามันถูกต้อง ตามเอกสาร MDN toISOStringนั้นแปลงเป็น UTC อย่างถูกต้อง[toISOString] returns a string in simplified extended ISO format ... The timezone is always zero UTC offsetและในตัวอย่างที่แสดงออฟเซ็ตจะถูกนำมาใช้ในกรณีที่เรียกว่า
FFF

560

เรียบง่ายและโง่

var date = new Date(); 
var now_utc =  Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),
 date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());

 return new Date(now_utc);

85
ฉันชอบความคิดของคุณและทำวิธีที่ฉันใช้มาหลายครั้งแล้ว function convertDateToUTC(date) { return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()); }
ทิม

21
รหัสที่สั้นที่สุดที่ฉันมาด้วยจะได้รับวัน UTC และเวลาโดยการตัดออกจากโซนเวลา:new Date(new Date().toUTCString().substr(0, 25))
joelvh

17
โปรดทราบว่า getUTCMonth () ส่งคืนค่า 0 ถึง 11 ดังนั้นหากคุณต้องการเดือนเป็นตัวเลขแทนที่จะเป็นสตริงมันจะช่วยให้ +1 มีค่า
Talvi Watia

19
นี่เป็นเรื่องไร้สาระ วันที่ใหม่จะมีค่าแตกต่างจากที่คุณต้องการจริงๆ เพียงแค่ใช้now.toUTCSTring()แทน now_utc.toString()(ผิด)
Bergi

22
ฉันจะไม่ใช้สิ่งนี้ - โดยใช้ Date ใหม่ () คุณจะได้เขตเวลาของ Brower ใน Chrome 29 และ IE10 วันที่ + เวลาดูเหมือนจะถูกต้อง แต่เขตเวลาถูกตั้งค่าเป็นเขตเวลาของเบราว์เซอร์ซึ่งอาจทำให้เกิดปัญหา ...
Sean

207

นี่คือวิธีการของฉัน:

var now = new Date();
var utc = new Date(now.getTime() + now.getTimezoneOffset() * 60000);

utcวัตถุผลลัพธ์ไม่ใช่วันที่ UTC จริง ๆ แต่วันที่ท้องถิ่นเปลี่ยนไปเพื่อให้ตรงกับเวลา UTC (ดูความคิดเห็น) อย่างไรก็ตามในทางปฏิบัติมันทำงาน


ฉันกำลังดูปัญหานั้นเมื่อฉันตระหนักว่าDate.now()ให้เวลาท้องถิ่นไม่ใช่เวลา UTC และวิธีนี้ดูเหมือนง่ายที่สุดสำหรับฉัน อย่างน้อยในกรณีของฉันที่ฉันต้องการเวลา UNIX และไม่ใช่สตริงที่จัดรูปแบบเป็นอย่างดี (ความแตกต่างเพียงอย่างเดียวคือฉันจะคูณด้วย60 * 1000เพื่อให้ชัดเจนยิ่งขึ้น :))
Timothée Boucher

18
การเพิ่ม 60000 * Date.getTimezoneOffset () ไม่ถูกต้อง! ก่อนอื่นคุณต้องนึกถึงวันที่ / เวลาทั้งหมดว่าเป็น UTC ด้วยตัวปรับเขตเวลาเพื่อการแสดงผล เบราว์เซอร์อาจแตกต่างกันอย่างไรก็ตาม Date.getTime () ส่งคืนจำนวนมิลลิวินาทีตั้งแต่ 1970-01-01 หากคุณสร้าง Date ใหม่โดยใช้หมายเลขนี้เช่น: new Date (Date.getTime ()); มันจะเป็น UTCอย่างไรก็ตามเมื่อคุณแสดง (เช่น: ผ่านคอนโซลเครื่องมือ dev dev ของ Chrome) จะปรากฏเป็นเขตเวลาท้องถิ่นของคุณ
Aaron Hoffman

15
ในเบราว์เซอร์ของฉันนี่จะสร้าง DateTime ที่ไม่ใช่ UTC อย่างไรก็ตามเมื่อแสดงภายในเบราว์เซอร์ของฉันจะแสดง DateTime ในเขตเวลาท้องถิ่นของฉันซึ่งจะเป็นเวลา UTC ที่ถูกต้องหากข้อมูลเขตเวลาถูกเพิกเฉย
Aaron Hoffman

Gotcha จุดที่น่าสนใจ ลองเปรียบเทียบnow.toString()กับutc.toString(): ไม่มีการเปลี่ยนแปลงเขตเวลา แต่การเปลี่ยนแปลงเวลาซึ่งค่อนข้างแตกต่างกัน อย่างไรก็ตามโซลูชันที่สะอาดกว่าจะซับซ้อนกว่านี้ (ฉันเดาเช่นนั้น) และรหัสนี้ทำงานในกรณีส่วนใหญ่ตราบใดที่ไม่มีการจัดการกับเขตเวลาเพิ่มเติม มันทำให้ฉันนึกถึงการชกต่อยเป็ด : สิ่งที่แตกต่าง แต่ทำเพื่อให้เหมือนกัน และโปรดสังเกตว่ารหัสของ DrunkCoder มีปัญหาเดียวกัน
Gras Double

4
คำตอบนี้แสดงให้เห็นถึงการใช้งานทั่วไปอีกครั้งของ "ยุคเปลี่ยน" ซึ่งเป็นอันตรายในการแยกตามที่มันสามารถล้มเหลวใกล้กรณีขอบเช่นการเปลี่ยน DST ไม่แนะนำ.
Matt Johnson-Pint

25
Date.prototype.toUTCArray= function(){
    var D= this;
    return [D.getUTCFullYear(), D.getUTCMonth(), D.getUTCDate(), D.getUTCHours(),
    D.getUTCMinutes(), D.getUTCSeconds()];
}

Date.prototype.toISO= function(){
    var tem, A= this.toUTCArray(), i= 0;
    A[1]+= 1;
    while(i++<7){
        tem= A[i];
        if(tem<10) A[i]= '0'+tem;
    }
    return A.splice(0, 3).join('-')+'T'+A.join(':');    
}

มันใช้งานได้ดี ฉันแค่ต้องการแทนที่ "-" ในวันที่ที่มาของฉันเป็น "/" เพื่อสร้างวันที่ JavaScript จากนั้นฉันสามารถเรียกใช้ฟังก์ชัน toISO () ของคุณเพื่อให้ได้ผลลัพธ์ที่ถูกต้อง
dthrasher

มันใช้งานได้ดี นอกจากนี้คุณยังสามารถป้อนผลลัพธ์ลงใน jQuery $ .parseDate (... ) เพื่อรับวัตถุวันที่กลับไปที่ UTC
Brian Ellis

23

แปลงเป็น ISO โดยไม่ต้องเปลี่ยนวันที่ / เวลา

var now = new Date(); // Fri Feb 20 2015 19:29:31 GMT+0530 (India Standard Time) 
var isoDate = new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString();
//OUTPUT : 2015-02-20T19:29:31.238Z

แปลงเป็น ISO พร้อมการเปลี่ยนวันที่ / เวลา (วันที่ / เวลาจะเปลี่ยนไป)

isoDate = new Date(now).toISOString();
//OUTPUT : 2015-02-20T13:59:31.238Z 

ลิงค์ซอ


ดังนั้นนี่คือการแกล้งทำ UTC? ฉันเปลี่ยนวันที่ในท้องถิ่นของฉันและฉันสามารถส่งวันและเวลาที่ฉันเห็นบนนาฬิกาพีซีของฉันไปยังเซิร์ฟเวอร์ได้สำเร็จ ว้าว. อย่างไรก็ตามดีกว่าการจัดแบ่งและแยกวิเคราะห์
Toolkit

นอกจากนี้คุณไม่จำเป็นต้อง. toISOString () คุณสามารถส่ง isoDate ไปยังเซิร์ฟเวอร์ได้
Toolkit

.toISOString () เป็นเรื่องง่ายและตรงไปตรงมาการออกจากมันจะเป็นขั้นตอนพิเศษ (isoDate ไม่ใช่ฟังก์ชั่น)
RollerCosta

คุณไม่จำเป็นต้องเพิ่มออฟเซ็ตแทนที่จะลบมันใช่ไหม อ้างถึงstackoverflow.com/a/11964609/832230
คิวเมนตัส

@ABB หากเขตเวลาชดเชยปัจจุบันเป็น + ve เราควรลบ (ในกรณีของเรา IST คือ +5: 30) มิฉะนั้นเพิ่ม
RollerCosta

18

เบราว์เซอร์อาจแตกต่างกันและคุณควรจำไว้ว่าอย่าเชื่อถือข้อมูลใด ๆ ที่ลูกค้าสร้างขึ้นซึ่งถูกกล่าวว่าข้อความด้านล่างใช้ได้กับฉัน (Google Chrome v24 บน Mac OS X 10.8.2)

var utcDate = new Date(new Date().getTime());


แก้ไข: "สิ่งนี้แตกต่างจากแค่new Date()อย่างไร" ดูที่นี่: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

  • หากไม่มีการระบุอาร์กิวเมนต์ตัวสร้างจะสร้างออบเจ็กต์วันที่ของ JavaScript สำหรับวันที่และเวลาปัจจุบันตามการตั้งค่าระบบ
  • หมายเหตุ: โดยที่วันที่เรียกว่าเป็นตัวสร้างที่มีมากกว่าหนึ่งอาร์กิวเมนต์อาร์กิวเมนต์ที่ระบุแสดงเวลาท้องถิ่น หากต้องการ UTC ให้ใช้ Date ใหม่ ( Date.UTC (... ) ) ด้วยอาร์กิวเมนต์เดียวกัน (หมายเหตุ: Date.UTC () ส่งคืนจำนวนมิลลิวินาทีตั้งแต่ 1970-01-01 00:00:00 UTC)

การเพิ่ม 60000 * Date.getTimezoneOffset () เนื่องจากคำตอบก่อนหน้านี้ระบุไว้ไม่ถูกต้อง ก่อนอื่นคุณต้องนึกถึงวันที่ / เวลาทั้งหมดว่าเป็น UTC ด้วยตัวปรับเขตเวลาเพื่อการแสดงผล

อย่างไรก็ตามเบราว์เซอร์อาจแตกต่างกันอย่างไรก็ตาม Date.getTime () ส่งคืนจำนวนมิลลิวินาทีนับตั้งแต่ 1970-01-01 UTC / GMT หากคุณสร้าง Date ใหม่โดยใช้หมายเลขนี้ตามที่ฉันทำด้านบนมันจะเป็น UTC / GMT อย่างไรก็ตามหากคุณแสดงผลโดยการเรียก. toString () มันจะปรากฏในเขตเวลาท้องถิ่นของคุณเพราะ. toString () ใช้เขตเวลาท้องถิ่นของคุณไม่ใช่เขตเวลาของวัตถุ Date ที่เรียกใช้

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

ในเบราว์เซอร์ของฉันเพิ่ม 60000 * Date.getTimezoneOffset () สร้าง DateTime ที่เป็นไม่ UTC อย่างไรก็ตามเมื่อแสดงภายในเบราว์เซอร์ของฉัน (เช่น:. toString ()) มันจะแสดง DateTime ในเขตเวลาท้องถิ่นของฉันที่จะแก้ไขเวลา UTC หากข้อมูลเขตเวลาถูกเพิกเฉย


11
ฉันเพิ่งรันโค้ดนี้บน Fx และ Chrome ดูเหมือนว่าจะไม่ทำงาน: ผลลัพธ์จะเหมือนกันทุกnew Date()ประการไม่ว่าจะเป็นการประทับเวลาหรือเปลี่ยนเขตเวลา
Gras Double

3
นั่นเป็นเพราะการประทับเวลานั้นใช้เขตเวลาน้อยกว่า new Date().getTime()จะส่งคืนการประทับเวลาที่ไม่เชื่อเรื่องพระเจ้าในเขตเวลาเสมอ ไม่มีการประทับเวลาที่เกี่ยวข้องจนกว่าคุณจะพยายามจัดรูปแบบเป็นสิ่งอื่นนอกเหนือจากจำนวนมิลลิวินาทีนับตั้งแต่ยุค Unix
frontendbeauty

7
เท่าที่ฉันสามารถบอกได้new Date(new Date().getTime())ว่าผลตอบแทนมีค่าเท่าnew Date()กันทุกประการ คุณอธิบายได้ไหมว่าคำตอบของคุณให้คุณค่าที่แตกต่างจากnew Date()อะไร
Kirk Woll

new Date("5/19/2014").getTime()ฉันโพสต์ค่านี้ไปยังเซิร์ฟเวอร์ของฉัน ตัวสร้าง Date สร้างวันที่โดยมีค่าชดเชย +7 บนเซิร์ฟเวอร์ (C #) new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(1401087600000)ผมเพิ่มค่าโพสต์เป็นมิลลิวินาทีในการยูนิกซ์ยุค 5/19/2014 7:00:00 AMผลที่ได้คือ ดังนั้นดูเหมือนว่า getTime () จะแสดงจำนวนมิลลิวินาทีรวมถึงอ็อฟเซ็ต UTC ของฉัน
xr280xr

1
มีความคิดเห็นจำนวนมากที่บ่นnew Date(new Date().getTime())ว่าไม่ได้ผล ฉันสามารถยืนยันได้ว่าnew Date(Date.UTC(2019, 8, 27, 0, 0, 0))สร้างเวลา UTC อย่างแน่นอน หากคุณล้มเหลวในการใช้งานDate.UTC(...)คุณจะได้รับวันที่ใน UTC ชดเชยในเขตเวลาของคุณ
Alex Barker

15
var myDate = new Date(); // Set this to your date in whichever timezone.
var utcDate = myDate.toUTCString();

1
วัตถุวันที่จะต้องมีการตั้งจริงวันที่ ด้านบนเป็นเพียงตัวอย่าง
James Skidmore

5
ตอนนี้ก็จะส่งคืน "Thu, 04 Jun 2009 04:10:56 GMT" ซึ่งไม่ใช่รูปแบบ ISO ที่จำเป็นใน OP
nickf

4
นี่เปลี่ยนเป็นสตริงซึ่งไม่ใช่วันที่
Anthony

2
ไม่จริงแล้วมันควรจะเป็นสตริงแทนวันที่ตาม OP
jcomeau_ictx

3
หลังจากแปลงเป็น UTC มันจะกลับมาในรูปแบบสตริงแล้ววิธีการเข้าถึงเช่น getMonth (), getDate () ฯลฯ
Sandeep sandy

10

อีกวิธีในการแปลงเป็น UTC และเก็บไว้เป็นวัตถุวันที่: (ใช้งานได้โดยเอาส่วน 'GMT' ออกจากจุดสิ้นสุดของสตริงที่จัดรูปแบบแล้วนำกลับไปไว้ในตัวสร้างวันที่)

var now = new Date();
var now_utc = new Date(now.toUTCString().slice(0, -4));

ฉันต้องทำสิ่งนี้เพื่อเชื่อมต่อกับไลบรารีตัวเลือกวันที่และเวลา แต่โดยทั่วไปมันเป็นความคิดที่ดีที่จะทำงานกับเดทด้วยวิธีนี้

โดยทั่วไปผู้ใช้ต้องการทำงานกับ datetimes ในเวลาท้องถิ่นของพวกเขาดังนั้นคุณสามารถปรับปรุงรหัสฝั่งเซิร์ฟเวอร์เพื่อแยกสตริง datetime กับ offsets อย่างถูกต้องแล้วแปลงเป็น UTC (ตัวเลือกที่ดีที่สุด) หรือคุณแปลงเป็นฝั่งไคลเอ็นต์สตริง UTC ก่อนส่งไปยัง เซิร์ฟเวอร์ (เหมือนในคำตอบของ Will Stern)


7

คุณพยายามแปลงวันที่เป็นสตริงเช่นนั้นหรือไม่?

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

Date.prototype.getISOString = function() {
    var zone = '', temp = -this.getTimezoneOffset() / 60 * 100;
    if (temp >= 0) zone += "+";
    zone += (Math.abs(temp) < 100 ? "00" : (Math.abs(temp) < 1000 ? "0" : "")) + temp;

    // "2009-6-4T14:7:32+10:00"
    return this.getFullYear()   // 2009
         + "-"
         + (this.getMonth() + 1) // 6
         + "-"
         + this.getDate()       // 4
         + "T"
         + this.getHours()      // 14
         + ":"
         + this.getMinutes()    // 7
         + ":"
         + this.getSeconds()    // 32
         + zone.substr(0, 3)    // +10
         + ":"
         + String(temp).substr(-2) // 00
    ;
};

หากคุณต้องการเวลา UTC เพียงแทนที่ฟังก์ชั่น get * ทั้งหมดด้วย getUTC * เช่น: getUTCFullYear, getUTCMonth, getUTCHours ... แล้วเพิ่ม "+00: 00" ที่ส่วนท้ายแทนการชดเชยเขตเวลาของผู้ใช้


1
นี่เป็นตัวอย่างแรกที่ฉันเห็นว่าพยายามจัดการกับเขตเวลาชดเชยดังนั้น +1 สำหรับสิ่งนั้น อย่างไรก็ตามฉันพบบางสิ่งด้วย - temp.substr (-2) ทำให้เกิดข้อผิดพลาดเนื่องจากเป็นตัวเลขไม่ใช่สตริงดังนั้นคุณต้องทำอะไรบางอย่างเช่น "temp = '' + temp;" ก่อนอื่นให้เปลี่ยนเป็นสตริง นอกจากนี้ฉันชอบ ISO ของฉันวันที่เป็นศูนย์ - เบาะ - ฉันคิดว่านี่ทำให้พวกเขามีมาตรฐานมากขึ้น
มิกเคอร์เซีย

@Mick - ฉันได้รับการปรับปรุงเพื่อแก้ไขข้อผิดพลาดนั้น ฉันใช้มาString(temp)ตั้งแต่วิธีอื่น ( "" + temp) มีรายงานว่าเป็นข้อผิดพลาด JSLint ในวันนี้
nickf

นี่คือมาตรฐานขณะนี้เป็นtoISOStringวิธีการ
Bergi

7
date = '2012-07-28'; stringdate = new Date(date).toISOString();

ควรทำงานในเบราว์เซอร์ที่ใหม่กว่าส่วนใหญ่ มันส่งคืน2012-07-28T00:00:00.000Zบน Firefox 6.0


7

คำแนะนำของฉันเมื่อทำงานกับวันที่คือการแยกวันที่ในแต่ละฟิลด์จากการป้อนข้อมูลของผู้ใช้ คุณสามารถใช้มันเป็นสายเต็ม แต่คุณกำลังเล่นกับไฟ

JavaScript สามารถรักษาวันที่เท่ากันสองวันในรูปแบบที่แตกต่างกัน

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse

ไม่เคยทำอะไรที่ชอบ:

new Date('date as text');

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

var year = getFullYear('date as text');
var month = getMonth('date as text');
var dayOfMonth = getDate('date as text');

var date = new Date(year, month, dayOfMonth);

var offsetInMs = ((date.getTimezoneOffset() * 60)  // Seconds
                 * 1000);                          //  Milliseconds

var utcDate = new Date(date.getTime + offsetInMs);

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


FYI getYear ถูกลบออกจากเว็บมาตรฐานdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ghan

6

หากคุณกำลังเผชิญกับการเดทมากมันก็คุ้มค่าที่จะใช้ moment.js ( http://momentjs.com ) วิธีการแปลงเป็น UTC จะเป็น:

moment(yourTime).utc()

คุณสามารถใช้รูปแบบเพื่อเปลี่ยนวันที่เป็นรูปแบบที่คุณต้องการ:

moment(yourTime).utc().format("YYYY-MM-DD")

มีตัวเลือกออฟเซ็ตในเวลาเช่นกัน แต่ก็มีห้องสมุดเสริมเพิ่มเติมสำหรับจัดการกับเขตเวลา ( http://momentjs.com/timezone/ ) การแปลงเวลาจะง่ายอย่างนี้:

moment.tz(yourUTCTime, "America/New_York")

ความแตกต่างระหว่างmoment(yourTime).utc()และ moment.utc(yourTime)คืออะไร ฉันมักจะใช้หลัง
ps0604

5

โซลูชันของฉันรักษาวันที่เหมือนกันไม่ว่าเขตเวลาใดจะถูกตั้งค่าไว้ที่ฝั่งไคลเอ็นต์ บางทีบางคนอาจพบว่ามีประโยชน์

กรณีการใช้งานของฉัน:

ฉันกำลังสร้างแอปสิ่งที่ต้องทำที่คุณกำหนดวันที่ของงานของคุณ วันนี้ควรคงที่ไม่ว่าคุณจะอยู่ในเขตเวลาใด

ตัวอย่าง. คุณต้องการโทรหาเพื่อนของคุณเวลา 8.00 น. ของวันที่ 25 มิถุนายน

คุณสร้างงานนี้ 5 วันก่อน (วันที่ 20 มิถุนายน) ในขณะที่คุณอยู่ในประเทศจีน

จากนั้นในวันเดียวกันคุณบินไปนิวยอร์กสองสามวัน

จากนั้นในวันที่ 25 มิถุนายนในขณะที่คุณยังอยู่ในนิวยอร์กคุณตื่นนอนเวลา 7:30 น. (ซึ่งหมายความว่าคุณควรได้รับการแจ้งเตือนงานใน 30 นาที (แม้จะเป็น 13:30 น. แล้วในประเทศจีนที่คุณอยู่) งาน)

ดังนั้นงานจะข้ามเขตเวลา มันหมายความว่า 'ฉันต้องการที่จะทำเวลา 08:00 น. ในเขตเวลาใดก็ตามที่ฉันจะเข้าไป'

สิ่งที่ฉันทำคือสมมุติว่า 'ฉันคิดว่าคุณอยู่ในเขตเวลาของลอนดอน - UTC' เสมอ

หมายความว่าอะไร - เมื่อผู้ใช้เลือกวันที่ในเขตเวลาของเขา / เธอ - ฉันแปลงวันที่นี้เป็นวันที่เดียวกันใน UTC กล่าวคือ คุณเลือกเวลา 8.00 น. ในประเทศจีน แต่ฉันแปลงเป็นเวลา 8:00 น. ใน UTC

จากนั้น - ครั้งต่อไปที่คุณเปิดแอป - ฉันอ่านวันที่บันทึกใน UTC และแปลงเป็นวันที่เดียวกันในเขตเวลาปัจจุบันของคุณ - ฉันแปลงเวลา 8.00 น. ใน UTC เป็นเวลา 8:00 น. ในเขตเวลานิวยอร์ก

วิธีการแก้ปัญหานี้หมายความว่าวันที่อาจมีความหมายอย่างอื่นขึ้นอยู่กับว่าคุณอยู่ที่ไหนเมื่อคุณตั้งค่าและที่ที่คุณกำลังอ่าน แต่มันยังคงคงที่ในลักษณะที่ 'รู้สึก' เหมือนคุณอยู่ในเขตเวลาเดียวกันเสมอ

ลองเขียนโค้ดกัน:

ครั้งแรก - เรามี 2 ฟังก์ชั่นหลักสำหรับการแปลงจาก / เป็น UTC โดยไม่สนใจเขตเวลา:

export function convertLocalDateToUTCIgnoringTimezone(date: Date) {
  const timestamp = Date.UTC(
    date.getFullYear(),
    date.getMonth(),
    date.getDate(),
    date.getHours(),
    date.getMinutes(),
    date.getSeconds(),
    date.getMilliseconds(),
  );

  return new Date(timestamp);
}

export function convertUTCToLocalDateIgnoringTimezone(utcDate: Date) {
  return new Date(
    utcDate.getUTCFullYear(),
    utcDate.getUTCMonth(),
    utcDate.getUTCDate(),
    utcDate.getUTCHours(),
    utcDate.getUTCMinutes(),
    utcDate.getUTCSeconds(),
    utcDate.getUTCMilliseconds(),
  );
}

จากนั้นฉันบันทึก / อ่านวันที่นี้เช่น:

function saveTaskDate(localDate: Date) {
  // I convert your local calendar date so it looks like you've picked it being in UTC somewhere around London
  const utcDate = convertLocalDateToUTCIgnoringTimezone(localDate);
  api.saveTaskDate(utcDate);
}

function readTaskDate(taskUtcDate: Date) {
  // I convert this UTC date to 'look in your local timezone' as if you were now in UTC somewhere around london
  const localDateWithSameDayAsUTC = convertUTCToLocalDateIgnoringTimezone(taskUtcDate);

  // this date will have the same calendar day as the one you've picked previously
  // no matter where you were saving it and where you are now
}

4

ฉันเพิ่งค้นพบว่ารุ่น 1.2.3 ของสตีเว่น Levithan ของdate.format.jsไม่เพียงแค่สิ่งที่ฉันต้องการ ช่วยให้คุณสามารถจัดหาสตริงรูปแบบสำหรับวันที่ JavaScript และจะแปลงจากเวลาท้องถิ่นเป็น UTC นี่คือรหัสที่ฉันใช้ตอนนี้:

// JavaScript dates don't like hyphens!    
var rectifiedDateText = dateText.replace(/-/g, "/");
var d = new Date(rectifiedDateText);

// Using a predefined mask from date.format.js.
var convertedDate = dateFormat(d, 'isoUtcDateTime'); 

9
นี่ไม่ใช่คำตอบที่ดีที่สุดสำหรับคำถามของคุณ คุณควรพิจารณาสิ่งที่ตอบคำถามของคุณโดยตรงหรือถามคำถามของคุณแตกต่างกัน
hitautodestruct

1
ฉันบังเอิญได้แก้ไขสคริปต์นี้ (และเวอร์ชั่น) เพราะมันไม่เพียงพอสำหรับ IE7 และ Firefox
Barbarrosa

4

ฉันพบว่าการแยกปลั๊กอินวันที่jQuery Globalizationทำงานได้ดีที่สุด วิธีการอื่นมีปัญหาข้ามเบราว์เซอร์และสิ่งต่างๆเช่น date.js ไม่ได้รับการอัปเดตในขณะนี้

คุณไม่ต้องการ datePicker บนหน้า คุณสามารถเรียกสิ่งที่คล้ายกับตัวอย่างที่ให้ไว้ในเอกสาร:

$.parseDate('yy-mm-dd', '2007-01-26');

1
เพียงเพราะบางสิ่งไม่ได้รับการอัปเดตไม่ได้หมายความว่าคุณไม่ควรใช้ Date.js ทำงานได้อย่างสมบูรณ์แบบมาหลายปีดังนั้นจึงไม่จำเป็นต้องอัปเดต วัตถุ JS Date และรูปแบบวันที่ที่ใช้งานไม่ได้เปลี่ยนแปลงในช่วงสองสามปีที่ผ่านมาดังนั้นทำไมสคริปต์ที่จัดการกับมัน Date.JS เป็นห้องสมุด JS Date ที่ดีที่สุด มีปัญหาเล็กน้อยสำหรับมันใน GitHub แต่อย่างอื่นมันสมบูรณ์แบบ github.com/datejs/Datejs
thugsb

3

ฟังก์ชั่นนี้ใช้งานได้ดีสำหรับฉัน

function ParseDateForSave(dateValue) {
    // create a new date object
    var newDate = new Date(parseInt(dateValue.substr(6)));

    // return the UTC version of the date
    return newDate.toISOString();
}


2
var userdate = new Date("2009-1-1T8:00:00Z");
var timezone = userdate.getTimezoneOffset();
var serverdate = new Date(userdate.setMinutes(userdate.getMinutes()+parseInt(timezone)));

สิ่งนี้จะให้วันและเวลา UTC ที่ถูกต้องแก่คุณ
มันเป็นเพราะgetTimezoneOffset()จะทำให้คุณมีความแตกต่างของเขตเวลาในไม่กี่นาที ฉันขอแนะนำให้คุณที่จะไม่ใช้toISOString()เพราะผลจะอยู่ในสตริงดังนั้นในอนาคตคุณจะไม่สามารถจัดการวันที่



2

หากคุณต้องการวัตถุวันที่

การผ่านสตริงวันที่เท่านั้น Date ใช้เวลาเป็น 00:00 เลื่อนตามเขตเวลา:

new Date('2019-03-11')
Sun Mar 10 2019 18:00:00 GMT-0600 (Central Standard Time)

หากคุณเพิ่มชั่วโมงและนาทีปัจจุบันคุณจะได้รับวันที่ที่ถูกต้อง:

new Date('2019-03-11 ' + new Date().getHours() + ':' + new Date().getMinutes())
Mon Mar 11 2019 04:36:00 GMT-0600 (Central Standard Time)

1

มองคำถามของคุณชัดเจนว่าคุณเพียงแค่ต้องการส่งช่วงวันที่ไปยังแบ็กเอนด์ของคุณสำหรับการโพสต์ต่อไป

ฉันสมมติว่าคุณกำลังปฏิบัติตามแนวทางข้อมูลมาตรฐานซึ่งคาดว่าข้อมูลจะอยู่ในรูปแบบเฉพาะ ตัวอย่างเช่นฉันใช้ ODATA ซึ่งเป็น RESTfull API ซึ่งคาดว่าวัตถุเวลาวันที่จะอยู่ในรูปแบบ: -

YYYY-MM-DDT00: 00: 00

ที่สามารถทำได้อย่างง่ายดายผ่านตัวอย่างที่โพสต์ด้านล่าง (โปรดเปลี่ยนรูปแบบตามความต้องการของคุณ)

var mydate;//assuming this is my date object which I want to expose var UTCDateStr = mydate.getUTCFullYear() + "-" + mydate.getUTCMonth() + "-" + mydate.getUTCDate() + "T00:00:00";

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

var mydate;//assuming this is my date object which I want to expose var UTCDate = new Date(mydate);/*create a copy of your date object. Only needed if you for some reason need the original local date*/ UTCDate.setTime(UTCDate.getTime() + UTCDate.getTimezoneOffset() * 60 * 1000);

ตัวอย่างโค้ดข้างต้นนั้นจะเพิ่ม / ลบเวลาที่เพิ่ม / ลบโดยเบราว์เซอร์ตามเขตเวลา

ตัวอย่างเช่นถ้าฉันอยู่ใน EST (GMT-5) และบริการของฉันส่งคืนวัตถุเวลาวันที่ = พุธ 17 ส.ค. 2016 00:00:00 GMT-0500 เบราว์เซอร์ของฉันจะลบการชดเชยเขตเวลาโดยอัตโนมัติ (5 ชั่วโมง) เพื่อรับเวลาท้องถิ่นของฉัน ดังนั้นถ้าฉันพยายามที่จะดึงเวลาที่ฉันได้รับพุธ 16 สิงหาคม 2016 19:00:00 GMT-0500 ทำให้เกิดปัญหามากมาย มีห้องสมุดจำนวนมากอยู่ข้างนอกซึ่งจะทำให้เรื่องนี้ง่ายขึ้น แต่ฉันต้องการแบ่งปันวิธีการ JS ที่บริสุทธิ์

สำหรับข้อมูลเพิ่มเติมโปรดดูที่: http://praveenlobo.com/blog/how-to-convert-javascript-local-date-to-utc-and-utc-to-local-date/ที่ฉันได้รับของฉัน แรงบันดาลใจ

หวังว่านี่จะช่วยได้!


1

วิธีการนี้จะทำให้คุณ: 2017-08-04T11:15:00.000+04:30และคุณสามารถละเว้นโซน2017-08-04T11:15:00.000ตัวแปรที่จะเพียงแค่ได้รับ

function getLocalIsoDateTime(dtString) {
    if(dtString == "")
        return "";
    var offset = new Date().getTimezoneOffset();
    var localISOTime = (new Date(new Date(dtString) - offset * 60000 /*offset in milliseconds*/)).toISOString().slice(0,-1);
    //Next two lines can be removed if zone isn't needed.
    var absO = Math.abs(offset);
    var zone = (offset < 0 ? "+" : "-") + ("00" + Math.floor(absO / 60)).slice(-2) + ":" + ("00" + (absO % 60)).slice(-2);
    return localISOTime + zone;
}

1

เมื่อใช้แพ็คเกจชั่วขณะคุณสามารถแปลงสตริงวันที่ของ UTC เป็นวัตถุวันที่ใหม่ได้อย่างง่ายดาย:

const moment = require('moment');
let b = new Date(moment.utc('2014-02-20 00:00:00.000000'));
let utc = b.toUTCString();
b.getTime();

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


4
แม้ว่านี่อาจตอบคำถาม แต่ก็ไม่มีคำอธิบายรหัสของคุณ โปรดอัปเดตคำตอบของคุณเพื่อให้คำอธิบายว่าคุณกำลังทำอะไรอยู่ ขอบคุณ!
Miroslav Glamuzina


0

ฉันรู้ว่าคำถามนี้เก่า แต่ได้ดูที่ปัญหาเดียวกันนี้และหนึ่งตัวเลือกจะส่ง date.valueOf () ไปยังเซิร์ฟเวอร์แทน ฟังก์ชั่น valueOf () ของวันที่จาวาสคริปต์ส่งจำนวนมิลลิวินาทีตั้งแต่เที่ยงคืนของวันที่ 1 มกราคม 1970 UTC

มูลค่าของ()


0

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

//First i had a string called stringDateVar that i needed to convert to Date
var newDate = new Date(stringDateVar)

//output: 2019-01-07T04:00:00.000Z
//I needed it 2019-01-07T00:00:00.000Z because i had other logic that was dependent on that 

var correctDate = new Date(newDate.setUTCHours(0))

//This will output 2019-01-07T00:00:00.000Z on everything which allows scalability 

0

เส้นด้ายเพิ่มช่วงเวลา

import moment from 'moment';

//local Js date to UTC using moment
const utcDate = moment.utc(moment(new date()).format('YYYY-MM-DDTHH:mm:ss')).valueOf();
console.log('UTC Date', utcDate);


// UTC to local date without moment
const localDate = convertUTCDateToLocalDate(new Date(utcDate))
console.log('UTC Date', moment(localDate).format('MMM D, YYYY HH:mm'));


function convertUTCDateToLocalDate(date) {

   let newDate = new Date(date.getTime() + date.getTimezoneOffset()*60*1000);

   const offset = date.getTimezoneOffset() / 60;
   const hours = date.getHours();

   newDate.setHours(hours - offset);

   return newDate;

}


-8

เรียบง่ายยิ่งขึ้น

myvar.setTime(myvar.getTime() + myvar.getTimezoneOffset() * 60000);

2
สิ่งนี้ไม่สมบูรณ์ setTimeพึ่งพาnew Dateซึ่งคุณไม่ได้รวมอยู่ด้วย กรุณาทำคำตอบให้สมบูรณ์
random_user_name

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