Phân tích ngày không có javascript múi giờ


147

Tôi muốn phân tích ngày mà không có múi giờ trong JavaScript. Tôi đã thử:

new Date(Date.parse("2005-07-08T00:00:00+0000"));

Trả về Thứ Sáu ngày 08 tháng 7 năm 2005 02:00:00 GMT + 0200 (Giờ ban ngày Trung Âu)

new Date(Date.parse("2005-07-08 00:00:00 GMT+0000"));

Trả về kết quả tương tự

new Date(Date.parse("2005-07-08 00:00:00 GMT-0000"));

Trả về kết quả tương tự

Tôi muốn phân tích thời gian:

  1. Không có múi giờ.

  2. Không gọi hàm tạo ngày.UTC hoặc Ngày mới (năm, tháng, ngày).

  3. Chỉ cần chuyển chuỗi đơn giản vào hàm tạo ngày (không có cách tiếp cận nguyên mẫu).

  4. Tôi phải Dateđối tượng sản phẩm , không String.


3
Bạn chỉ có thể bỏ qua Date.parsebtw và truyền trực tiếp chuỗi cho hàm Datetạo.
Bergi

1
Tôi không chắc tại sao bạn cần điều này nhưng tôi khá chắc chắn Ngày luôn có múi giờ địa phương của người dùng. Nếu bạn muốn JavaScript của bạn hoạt động với các múi giờ khác ngoài bạn sẽ phải sử dụng một đối tượng trình bao cho Ngày, có thể điều này sẽ hiệu quả với bạn: github.com/mde/timezone-js
HMR

1
Thật không may, tôi đã phải sao chép Dateđối tượng để có được đối tượng chính xác để so sánh ngày trong MongoDB:new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate())
Athlan

Nếu bạn muốn phân tích một ngày mà không có thời gian, bạn cần chỉ định múi giờ bạn muốn giả sử, vì "2005-07-08" có nghĩa là những thứ khác nhau trong các múi giờ khác nhau. Kể từ tháng 5 năm 2020, tài liệu MDN khuyên không nên sử dụng bất kỳ tính năng phân tích cú pháp Ngày nào vì sự khác biệt trong cách triển khai. Tuy nhiên, sử dụng Date.parse ("2005-07-08") có thể sẽ trả về thời gian 00:00 UTC. Mặt khác, phân tích ngày tháng, sẽ trả về 00:00 giờ địa phương khi phân tích chuỗi cùng ngày
Andy

Câu trả lời:


106

Ngày được phân tích cú pháp chính xác, đó chỉ là toString chuyển đổi nó thành múi giờ địa phương của bạn:

let s = "2005-07-08T11:22:33+0000";
let d = new Date(Date.parse(s));

// this logs for me 
// "Fri Jul 08 2005 13:22:33 GMT+0200 (Central European Summer Time)" 
// and something else for you

console.log(d.toString()) 

// this logs
// Fri, 08 Jul 2005 11:22:33 GMT
// for everyone

console.log(d.toUTCString())

Đối tượng ngày Javascript là dấu thời gian - chúng chỉ chứa một số mili giây kể từ thời đại. Không có thông tin múi giờ trong một đối tượng Ngày. Ngày dương lịch nào (ngày, phút, giây) dấu thời gian này đại diện cho vấn đề diễn giải (một trong các to...Stringphương pháp).

Ví dụ trên cho thấy ngày đang được phân tích cú pháp chính xác - nghĩa là, nó thực sự chứa một lượng mili giây tương ứng với "2005-07-08T11: 22: 33" trong GMT.


4
Thật không may Tôi phải tạo đối tượng Date, không phải String.
Athlan

@Athlan: thêm một số giải thích.
georg

1
Tôi đã kiểm tra nó. Tôi đã chuyển ngày được phân tích cú pháp vào truy vấn MongoDB new Date(Date.parse("2005-07-08T11:22:33+0000"))và ngày được sao chép qua hàm tạo : new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate()). Cả hai giải pháp, kết quả khác nhau, thứ hai đúng! Câu trả lời của bạn rất hữu ích, chỉ được đề cập trong hunlock.com/bloss/Javascript_Dates-The_Complete_Reference . Lên.
Athlan

Làm việc hoàn hảo với tôi - .toUTCString () là tấm vé mang lại cho tôi thời gian chính xác từ chuỗi ban đầu đã cho. tức là ngày mới ("2016-08-22T19: 45: 00.0000000"). toUTCString ()
Michael Giovanni Pumo

38
Nguồn gốc của tất cả các tội ác trong ngày và thời gian JavaScript được chứa trong câu đầu tiên của bạn ... Chỉ là để BẮT ĐẦU CHUYỂN ĐỔI vào múi giờ địa phương của bạn ... Đâu là trách nhiệm duy nhất trong vấn đề này? Phương thức toString chỉ nên xâu chuỗi kết quả và không chuyển đổi nó. Nếu tôi muốn ngày được chuyển đổi, tôi nên có các phương pháp khác để làm điều đó.
neo

109

Tôi có cùng một vấn đề. Tôi nhận được một ngày dưới dạng Chuỗi, ví dụ: '2016-08-25T00: 00: 00', nhưng tôi cần phải có đối tượng Ngày với thời gian chính xác. Để chuyển đổi String thành đối tượng, tôi sử dụng getTimezone Offerset:

var date = new Date('2016-08-25T00:00:00')
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
new Date(date.getTime() - userTimezoneOffset);

getTimezoneOffset()sẽ trả lại ether âm hoặc giá trị dương. Điều này phải được trừ để làm việc ở mọi địa điểm trên thế giới.


6
Tôi có cùng một vấn đề và thấy điều này là hữu ích. Tuy nhiên, tôi thấy rằng điều này không xử lý việc bù múi giờ do thời gian tiết kiệm ánh sáng ban ngày. Ví dụ: Tôi đang ở PST nên phần bù hiện tại của tôi (vào tháng 3) từ GMT là -8: 00, nhưng vào tháng 5 sẽ là -7: 00. Giải pháp của tôi là tính toánvar userTimezoneOffset = date.getTimezoneOffset()*60000;
mmh02

3
Trừ khi tôi là một thằng ngốc hoàn toàn, điều này thực sự trả lại sai thời điểm. getTimezoneOffset()trả về số phút theo hướng ngược lại mà bạn nghĩ - múi giờ của tôi là UTC-4 ngay bây giờ nhưng getTimezoneOffset()trả về 240 dương. Do đó, userTimezoneOffsetnên được trừ đi date.getTime(), không được thêm vào nó.
vaindil

1
Tôi sẽ đồng ý với @vaindil bạn nên trừ đi. Giải pháp của wakwa chỉ hoạt động khi bạn ở bên chính xác của Greenwich. Wakwas nên sửa nó.
Janne Harju

1
Ah! nói quá sớm Nó không hoạt động trong hầu hết các múi giờ. Tôi có thể xác nhận rằng nó trả về một ngày sai khi bù lần AEST & CEST với giờ GMT.
saran3h

1
@vaindil bây giờ kết quả giống như new Date('2016-08-25T00:00:00Z')tôi nghĩ rằng vấn đề là phải thao túng new Date('2016-08-25T00:00:00Z')để giờ địa phương được hiển thị với thời gian 0:00 nhưng mã này bị bỏ lỡZ
barbsan

14

Tôi gặp vấn đề tương tự và sau đó nhớ ra một điều gì đó không hay về một dự án cũ mà tôi đang thực hiện và cách họ xử lý vấn đề này. Lúc đó tôi không hiểu và không thực sự quan tâm cho đến khi tôi gặp phải vấn đề

var date = '2014-01-02T00:00:00.000Z'
date = date.substring(0,10).split('-')
date = date[1] + '-' + date[2] + '-' + date[0]

new Date(date) #Thu Jan 02 2014 00:00:00 GMT-0600

Vì bất kỳ lý do gì, việc vượt qua ngày trong '01 -02-2014 'đặt múi giờ về 0 và bỏ qua múi giờ của người dùng. Đây có thể là một con sán trong lớp Date nhưng nó đã tồn tại một thời gian trước đây và tồn tại đến ngày nay. Và nó dường như hoạt động trên nhiều trình duyệt. Hãy thử nó cho chính mình.

Mã này được triển khai trong một dự án toàn cầu, nơi các múi giờ rất quan trọng nhưng người nhìn vào ngày không quan tâm đến thời điểm chính xác được giới thiệu.


Tôi nghĩ đó là cố ý vì "Z" chỉ định UTC mà JS sau đó chuyển đổi, nhưng không có múi giờ nên nó không thể chuyển đổi nó vì vậy về cơ bản nó giả định múi giờ của người dùng. Rất muốn nhận được một số xác nhận hoặc giải thích tốt hơn mặc dù.
dlsso

7
Các hành vi mạnh mẽ là do dấu gạch ngang. Chrome, Firefox và IE11 đều diễn giải 2014/5/312014/05/31như Sat ngày 31 tháng 5 năm 2014 00:00:00 GMT-0600 (Giờ ban ngày miền núi) `(MDT là múi giờ hiện tại của tôi). Với dấu gạch ngang ... tất cả các trình duyệt diễn giải 2014-05-31là Thứ Sáu ngày 30 tháng 5 năm 2014 18:00:00 GMT-0600 (Giờ ban ngày miền núi). Thật kỳ lạ, với 2014-5-31, Chrome trả lại vào Thứ Bảy, Firefox trả lại vào Thứ Sáu và IE11 cho biết ngày này không hợp lệ. Có vẻ như date.replace('-','/')có thể làm một mẹo.
atheaos

6

Bản Datethân đối tượng sẽ chứa múi giờ và kết quả trả về là hiệu ứng chuyển đổi nó thành chuỗi theo cách mặc định. Tức là bạn không thể tạo một đối tượng ngày mà không có múi giờ. Nhưng những gì bạn có thể làm là bắt chước hành vi của Dateđối tượng bằng cách tạo ra đối tượng của riêng bạn. Này được, tuy nhiên, tốt hơn để được bàn giao cho các thư viện như moment.js .


2
Thật không may Tôi phải tạo đối tượng Date, không phải String.
Athlan

3

giải pháp đơn giản

const handler1 = {
  construct(target, args) {
    let newDate = new target(...args);
    var tzDifference = newDate.getTimezoneOffset();
    return new target(newDate.getTime() + tzDifference * 60 * 1000);
  }
};

Date = new Proxy(Date, handler1);

3

Ngày trong javascript chỉ là giữ cho nó đơn giản bên trong. vì vậy dữ liệu thời gian ngày được lưu trữ trong UTC unix epoch (mili giây hoặc ms).

Nếu bạn muốn có thời gian "cố định" không thay đổi theo bất kỳ múi giờ nào trên trái đất, bạn có thể điều chỉnh thời gian trong UTC để khớp với múi giờ địa phương hiện tại của mình và lưu lại. Và khi truy xuất nó, trong bất kỳ múi giờ địa phương nào bạn đang ở, nó sẽ hiển thị thời gian UTC được điều chỉnh dựa trên người đã lưu nó và thêm phần bù múi giờ cục bộ để có thời gian "cố định".

Để lưu ngày (tính bằng ms)

toUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC - offset; // UTC - OFFSET
}

Để truy xuất / hiển thị ngày (tính bằng ms)

fromUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC + offset; // UTC + OFFSET
}

Sau đó bạn có thể:

const saveTime = new Date(toUTC(Date.parse("2005-07-08T00:00:00+0000")));
// SEND TO DB....

// FROM DB...
const showTime = new Date(fromUTC(saveTime));

2

Bạn có thể sử dụng mã này

var stringDate = "2005-07-08T00:00:00+0000";
var dTimezone = new Date();
var offset = dTimezone.getTimezoneOffset() / 60;
var date = new Date(Date.parse(stringDate));
date.setHours(date.getHours() + offset);

1
Tôi không tin rằng điều này sẽ tính đến khoản tiết kiệm ánh sáng ban ngày
Daniel Thompson

2

Vì đây thực sự là một vấn đề định dạng khi hiển thị ngày (ví dụ: hiển thị theo giờ địa phương), tôi muốn sử dụng đối tượng Intl.DateTimeFormat (ish) mới để thực hiện định dạng vì nó rõ ràng hơn và cung cấp nhiều tùy chọn đầu ra hơn:

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };

const dateFormatter = new Intl.DateTimeFormat('en-US', dateOptions);
const dateAsFormattedString = dateFormatter.format(new Date('2019-06-01T00:00:00.000+00:00'));

console.log(dateAsFormattedString) // "June 1, 2019"

Như được hiển thị, bằng cách đặt timeZone thành 'UTC', nó sẽ không thực hiện chuyển đổi cục bộ. Là một phần thưởng, nó cũng cho phép bạn tạo ra các đầu ra bóng bẩy hơn. Bạn có thể đọc thêm về Intl.DateTimeFormat đối tượng từ Mozilla - Intl.DateTimeFormat .

Biên tập:

Các chức năng tương tự có thể đạt được mà không cần tạo một Intl.DateTimeFormatđối tượng mới . Đơn giản chỉ cần chuyển các tùy chọn miền và ngày trực tiếp vào toLocaleDateString()chức năng.

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };
const myDate = new Date('2019-06-01T00:00:00.000+00:00');
today.toLocaleDateString('en-US', dateOptions); // "June 1, 2019"

1

Chỉ là một ghi chú chung chung. một cách để giữ cho nó linh hoạt.

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

Chúng tôi có thể sử dụng getMinutes (), nhưng nó chỉ trả về một số trong 9 phút đầu tiên.

let epoch = new Date() // Or any unix timestamp

let za = new Date(epoch),
    zaR = za.getUTCFullYear(),
    zaMth = za.getUTCMonth(),
    zaDs = za.getUTCDate(),
    zaTm = za.toTimeString().substr(0,5);

console.log(zaR +"-" + zaMth + "-" + zaDs, zaTm)

Date.prototype.getDate()
    Returns the day of the month (1-31) for the specified date according to local time.
Date.prototype.getDay()
    Returns the day of the week (0-6) for the specified date according to local time.
Date.prototype.getFullYear()
    Returns the year (4 digits for 4-digit years) of the specified date according to local time.
Date.prototype.getHours()
    Returns the hour (0-23) in the specified date according to local time.
Date.prototype.getMilliseconds()
    Returns the milliseconds (0-999) in the specified date according to local time.
Date.prototype.getMinutes()
    Returns the minutes (0-59) in the specified date according to local time.
Date.prototype.getMonth()
    Returns the month (0-11) in the specified date according to local time.
Date.prototype.getSeconds()
    Returns the seconds (0-59) in the specified date according to local time.
Date.prototype.getTime()
    Returns the numeric value of the specified date as the number of milliseconds since January 1, 1970, 00:00:00 UTC (negative for prior times).
Date.prototype.getTimezoneOffset()
    Returns the time-zone offset in minutes for the current locale.
Date.prototype.getUTCDate()
    Returns the day (date) of the month (1-31) in the specified date according to universal time.
Date.prototype.getUTCDay()
    Returns the day of the week (0-6) in the specified date according to universal time.
Date.prototype.getUTCFullYear()
    Returns the year (4 digits for 4-digit years) in the specified date according to universal time.
Date.prototype.getUTCHours()
    Returns the hours (0-23) in the specified date according to universal time.
Date.prototype.getUTCMilliseconds()
    Returns the milliseconds (0-999) in the specified date according to universal time.
Date.prototype.getUTCMinutes()
    Returns the minutes (0-59) in the specified date according to universal time.
Date.prototype.getUTCMonth()
    Returns the month (0-11) in the specified date according to universal time.
Date.prototype.getUTCSeconds()
    Returns the seconds (0-59) in the specified date according to universal time.
Date.prototype.getYear()
    Returns the year (usually 2-3 digits) in the specified date according to local time. Use getFullYear() instead. 

-1

(new Date().toString()).replace(/ \w+-\d+ \(.*\)$/,"")

Điều này sẽ có đầu ra: Thứ ba ngày 10 tháng 7 năm 2018 19:07:11

(new Date("2005-07-08T11:22:33+0000").toString()).replace(/ \w+-\d+ \(.*\)$/,"")

Điều này sẽ có đầu ra: Thứ Sáu ngày 08 tháng 7 năm 2005 04:22:33

Lưu ý: Thời gian trả về sẽ phụ thuộc vào múi giờ địa phương của bạn


-1

Đây là giải pháp mà tôi đã đưa ra cho vấn đề này phù hợp với tôi.


thư viện được sử dụng: khoảnh khắc với lớp Ngày javascript đơn giản.

Bước 1. Chuyển đổi chuỗi ngày thành đối tượng khoảnh khắc (PS: khoảnh khắc giữ lại ngày và giờ gốc miễn là toDate()phương thức không được gọi):

const dateMoment = moment("2005-07-08T11:22:33+0000");

Bước 2. Trích xuất hoursminutescác giá trị từ đối tượng khoảnh khắc được tạo trước đó:

  const hours = dateMoment.hours();
  const mins = dateMoment.minutes();

Bước 3. Chuyển đổi khoảnh khắc thành Ngày (PS: điều này sẽ thay đổi ngày ban đầu dựa trên múi giờ của trình duyệt / máy của bạn, nhưng đừng lo lắng và đọc bước 4.):

  const dateObj = dateMoment.toDate();

Bước 4. Đặt thủ công giờ và phút trích xuất trong Bước 2.

  dateObj.setHours(hours);
  dateObj.setMinutes(mins);

Bước 5. dateObj bây giờ sẽ hiển thị Ngày ban đầu mà không có chênh lệch múi giờ. Ngay cả thay đổi thời gian ban ngày cũng sẽ không có bất kỳ ảnh hưởng nào đến đối tượng ngày vì chúng ta đang cài đặt thủ công giờ và phút ban đầu.

Hi vọng điêu nay co ich.


-7

Có một số vấn đề cố hữu với phân tích ngày mà không may được giải quyết tốt theo mặc định.

-Những ngày có thể đọc được của con người có múi giờ ẩn trong đó
-Có nhiều định dạng ngày được sử dụng rộng rãi trên web không rõ ràng

Để giải quyết những vấn đề này một cách dễ dàng và sạch sẽ, người ta sẽ cần một chức năng như thế này:

>parse(whateverDateTimeString,expectedDatePattern,timezone)
"unix time in milliseconds"

Tôi đã tìm kiếm cái này, nhưng không tìm thấy cái gì như thế!

Vì vậy, tôi đã tạo: https://github.com/zsoltszabo/timestamp-grabber

Thưởng thức!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.