Tarihi belirli bir saat diliminde biçimlendirme


177

Web uygulamamdaki tarihleri ​​ayrıştırmak ve biçimlendirmek için Moment.js kullanıyorum . Bir JSON nesnesinin parçası olarak, arka uç sunucum tarihleri ​​UTC çağından (Unix ofseti) milisaniye olarak gönderir.

Belirli bir saat diliminde tarihleri ​​ayrıştırmak kolaydır - ayrıştırmadan önce dizenin sonuna RFC 822 saat dilimi tanımlayıcısını eklemeniz yeterlidir:

// 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>

Ancak belirli bir saat dilimindeki tarihi nasıl biçimlendiririm ?

Tarayıcının geçerli saatine bakılmaksızın tutarlı sonuçlar istiyorum, ancak tarihleri ​​UTC olarak görüntülemek istemiyorum.


2
Moment henüz bunu desteklemiyor, ancak üzerinde çalışıyorlar. github.com/timrwood/moment/pull/671
Ben

5
Bu sadece işe yaramalı. İstenilen ofseti içeren bir zaman dizesini geçerseniz, tarayıcıyı yerel saate otomatik olarak ayarlamak yerine, ofseti korumalı ve yerel saati gösterildiği gibi görüntülemelidir. Tarayıcı-yerel saate ayarlamasını isteseydim, açıkça kullanmak için bir mahsup vermek yerine bir UTC zamanı verirdim. Demek istediğim ... Açık bir ofset veriyorum, neden temelde yiyor ve tarayıcı ofsetine kendi dönüşümünü yapıyor. Korkunç tasarım.
Triynko

@Triynko ofsetleri gün ışığından yararlanır, bu nedenle her zaman beklendiği gibi çalışmaz.
pinkpanther

1
Bununla ilgili bir şey, belirli bir formatta zaman yazdırmak istiyorum, örneğin 15 Mart 2018, ancak bunu yapmak için format dizesini bulamıyorum. DD MMM, YYYYGibi kullandığımda genel çalışmaz moment.tz("2018-02-15T14:20:00.000+0530", "Asia/Bangkok").format("DD MMM, YYYY"). Birisi bana bu api kullanırken zaman biçimlendirme için tüm anahtarları bulabilirsiniz belgelerinde işaret edebilir.
pRmdk

@PramodKumar Sorun nedir? Bu verir "15 Feb, 2018". Eğer biçim dizesi kullanmak kastettiniz DD MMMM, YYYYolsun "15 February, 2018"?
quietmint

Yanıtlar:


248

İşaret edildiği gibi Manto cevap , .utcOffset()Moment 2.9.0 itibariyle tercih edilen yöntemdir. Bu işlev, ters ofseti değil, UTC'den gelen gerçek ofseti kullanır (örneğin, DST sırasında New York için -240). "+0400" gibi ofset dizeleri öncekilerle aynıdır:

// 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')

Yaşlı .zone()pasörlük edildi kaldırılmış Moment.js 2.9.0 yılında. Saat dilimi tanımlayıcısını içeren bir dize (ör., -4 saat boyunca "-0400" veya "-04: 00") veya UTC'nin arkasındaki dakikaları temsil eden bir sayı (ör. DST sırasında New York için 240 ) içeren bir dize kabul etti .

// 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')

Sayısal ofsetler yerine adlandırılmış saat dilimleriyle çalışmak için Moment Timezone'u ekleyin ve .tz()bunun yerine şunu kullanın:

// 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 hiçbir yöntem 'format'" hatası ile bu sorun yaşıyordum. Bölgenin yalnızca 2.1.0 sürümünde ve Moment.js ve üzeri sürümlerde ayarlayıcı olarak kullanılabildiğini fark ettim (ve daha eski bir sürümdeydim). Teşekkürler!
Melinda Weathers

5
@ebi Varsayılan olarak tarayıcının saat dilimini zaten kullanıyor. To erişmek tarayıcının ofset saat dilimini kullanımını .zone()UTC (örneğin iadeler standart süre içinde New York için 300) birkaç dakika döndüren bir getter olarak.
quietmint

1
@EricCope Hayır, pek değil. Sen edebilirsiniz kullanmak .tz("America/Phoenix")size eklerseniz momentjs.com/timezone de ancak. Cevabı bir örnekle güncelledim.
quietmint

1
Zaman diliminin gün ışığından yararlanma nedeniyle farklı ofsetleri varsa, ofseti kullanmanın beklendiği gibi çalışmadığını unutmayın.
pinkpanther

1
.UtcOffset () otomatik olarak yaz saatini yönetecek mi? Kışın UTC +1 CET ayarladığımda olduğu gibi Yaz saati boyunca UTC +2 CEST bahis yapar mı? Çünkü bu kullanılabilir mi değil mi!
haemse

61

Moment-timezone kullanın

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

Belirli bir saat dilimine erişmeden önce, bu şekilde yüklemeniz gerekir (veya burada açıklanan alternatif yöntemleri kullanarak )

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

Soru sorulduğunda tz anının mevcut olduğunu düşünmüyorum, ama bunun yolun olabileceğini düşünüyorum. Şu anda MySQL'de UTC olarak depolanan tüm zaman damgaları ile benzer bir sorun üzerinde çalışıyorum, ancak istemcinin saat dilimi değil, kullanıcı yapılandırmasına bağlı belirli bir bölgede görüntülenecek.
nickdnk

47

Birkaç cevap, moment-saat diliminin adlandırılmış saat dilimi ile gitmenin yolu olduğunu belirtiyor. Sadece bu kütüphane hakkında oldukça kafa karıştırıcı olan bir şeyi açıklığa kavuşturmak istiyorum. Bu iki ifade arasında bir fark vardır:

moment.tz(date, format, timezone)

moment(date, format).tz(timezone)

İletilen tarihte bir saat dilimi belirtilmediğini varsayarsak:

İlk kod tarihi alır ve saat diliminin geçirilen kod olduğunu varsayar. İkincisi tarih alır, saat dilimini tarayıcıdan alır ve ardından saati ve saat dilimini geçirilen saat dilimine göre değiştirir.

Misal:

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"

Saat dilimim utc ile +5 arasında. Yani ilk durumda değişmez ve utc saat dilimi için tarih ve saati ayarlar.

İkinci durumda, geçilen tarihin -5 olduğunu varsayar, sonra UTC'ye çevirir ve bu yüzden "2018-07-18T00: 00: 00Z" tarihini tükürür.

NOT: format parametresi gerçekten önemlidir. Atlanan an, öngörülemeyen davranışlar içerebilen Date sınıfına geri dönebilirse


Saat diliminin, iletildiği tarihte belirtildiği varsayılarak:

Bu durumda ikisi de eşit davranıyor


Şimdi neden bu şekilde çalıştığını anlasam da, bunun oldukça kafa karıştırıcı bir özellik olduğunu ve açıklamaya değer olduğunu düşündüm.


1
tz bir işlev değildir
K - SO'daki toksisite büyüyor.

5
Moment-timezone yüklediniz mi?
Nicola Pedretti

biçimlendirmeden ayrıştırılmış ve dönüştürülmüş anı geri almanın bir yolu var mı? Örneğin, yeniden ayrıştırmadan farklı yollar biçimlendirmek istersem.
jEremyB

Bunu açıkladığınız için teşekkür ederiz. Kullanıcının tarayıcı saat diliminden farklı bir saat dilimi ayarlarken sorun yaşadım ve sorun tam da buydu.
Robin Schaaf

20

.zone () kullanımdan kaldırılmıştır ve bunun yerine utcOffset kullanmalısınız:

// for a timezone that is +7 UTC hours
moment(1369266934311).utcOffset(420).format('YYYY-MM-DD HH:mm')

8

Moment.js ile de aynı sorunu yaşıyordum. An saat dilimini yükledim, ancak sorun çözülmedi. Sonra, burada maruz kaldığı şeyi yaptım, saat dilimini ayarladım ve bir cazibe gibi çalışıyor:

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

Çok teşekkürler!


16
Yapıcıyı kullanmamalısınız new Date(). Moment, tarihleri ​​ayrıştırmak için ihtiyacınız olan her şeyi sağlar. Bkz . Dokümanları ayrıştırma .
quietmint

Evet, ama bunu yapmazsam,
An'dan

7
Uyarı, Moment'in dahili olarak yaptığınız şeye ( new Date()dahili olarak kullanarak ) geri döndüğü anlamına gelir , ancak bu tarayıcılar arasında tutarsızdır . Bunun yerine, ikinci argüman olarak beklenen formatı sağlamanız gerekir. Örnek: moment("12-25-1995", "MM-DD-YYYY").
quietmint

4

Yeni geldi ve aynı sorunu yaşadığım için, bulduğum sonuçları yayınladım

ayrıştırma yaparken, ofseti güncelleyebilirsiniz (yani bir veri ayrıştırıyorum (1.1.2014) ve sadece 1 Ocak 2014 tarihini istiyorum. GMT + 1'de 31.12.2013 alacağım. Bu yüzden önce değeri dengeledim.

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

Zaman dilimlerini desteklemem için kullanışlı geldi

B


-7

Bunu deneyebilirsiniz,

Burada, İstemci Saat Dilimi'ne (Tarayıcı) göre tarihi alabilirsiniz.

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

Normal ifade temel olarak ofset değerini alır.

Alkış !!


Genellikle, an ihtiyacınız olan her şeyi size verir. Asla özel bir şeyle eşleşmeniz gerekmez.
Mahesh Samudra
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.