2016-01-21 7 views
5

मान लें कि मेरे डेटाबेस में कोई व्यक्ति -73440000 यूनिक्स समय पर पैदा हुआ था। इसका मतलब है कि वह -Sep-1967 यूटीसी पर पैदा हुआ है लेकिन -Sep-1967 EDT। मैं EDT में के प्रत्येक दिन पैदा हुए लोगों की संख्या की गणना कैसे करूं?3-सितंबर-1 9 67 ईडीटी पर पैदा हुए # लोगों की गणना कैसे करें जब तारीख यूनिक्स टाइमस्टैम्प के रूप में संग्रहीत की जाती है?


बल्ले बंद ठीक है, आपको लगता है कि

SELECT FROM_UNIXTIME(-73440000) 
-- returns NULL 

रिटर्न NULL की खोज करेंगे। MySQL नकारात्मक यूनिक्स टाइमस्टैम्प को संभाल नहीं सकता है।

ठीक है, हम चाहते हैं कि आस-पास काम कर सकते हैं:

select date_add('1970-01-01', interval -73440000 second) 
-- returns 1967-09-04 00:00:00 

1967-09-04 00:00:00 जो यूटीसी में अपनी जन्मतिथि है अर्जित करता है।

हम EDT (टोरंटो समय) में बदलने के लिए कोशिश कर सकते हैं:

select convert_tz('1967-09-04 00:00:00','UTC','America/Toronto') 
-- returns 1967-09-04 00:00:00, but should be 1967-09-03 20:00:00 

लेकिन के रूप में यह पता चला है, CONVERT_TZ तारीखों पर या तो काम नहीं करता है 1970 तक पहले।

(मैं installed the timezones already है और यह 1970 और 2038 के बीच तारीखों को काम करता है) तो अब मैं अटक कर रहा हूँ

। मुझे यूनिक्स टाइमस्टैम्प को एक MySQL DATE में कनवर्ट करने की आवश्यकता है ताकि मैं इसके द्वारा समूह कर सकूं और फिर इसे COUNT कर सकूं। एकमात्र अन्य विकल्प जिसे मैं सोच सकता हूं प्रत्येक डेटाबेस में यूनिक्स टाइमस्टैम्प के रूप में रिकॉर्ड करना और रूपांतरण करने के लिए दूसरी भाषा का उपयोग करना और उन्हें टैली करना है, लेकिन अगर लाखों रिकॉर्ड हैं तो थोड़ा हास्यास्पद हो सकता है।

एनबी। आप ईडीटी और यूटीसी के बीच घंटे ऑफसेट की गणना नहीं कर सकते हैं क्योंकि यह पूरे वर्ष (डेलाइट बचत) में बदल सकता है।

+0

आप इस जाँच कर सके कृपया http://stackoverflow.com/questions/14454304/convert-tz-returns-null? यह एक ही समस्या हो सकती है। – FZE

+1

@ FeyyazEsatoğlu हाँ, मैं कुछ महीने पहले ही उस प्रश्न पर आया हूं। मैंने टाइमज़ोन को पहले से ही MySQL में स्थापित किया है - यह अब पूर्ण नहीं लौटाता है। हालांकि, 1 9 70 से पहले की तारीखों के लिए यह तारीख के रूप में, कोई रूपांतरण नहीं देता है। मुझे इसे पोस्ट करना चाहिए था। – mpen

+0

ठीक है, डेटा को फ़िक्र करने के बारे में कैसे? जैसा कि हम जानते हैं कि टाइमस्टैम्प 22xx तक जा सकता है, अब से 100 साल जोड़ें, और 'CONVERT_TZ' को बेवकूफ बनाओ और आप डेटा को बेवकूफ़ बनाते समय कॉलम जोड़ सकते हैं '1 = 0' फिर सही तिथि खोजने के लिए चयन और घटाकर लपेटें। क्या यह संभव नहीं है? एक विचार है। – FZE

उत्तर

3

आप मैन्युअल रूप से रूपांतरण कर सकते हैं; यदि आप पहले से ही तो MySQL में लोड क्षेत्र डेटा मिल गया है आप पहले से ही वापस 1918 के लिए जा रहा सूची पर एक नज़र डालते हैं डेटा मिल गया है:

SET @timezone = "America/Toronto"; 
SELECT FROM_UNIXTIME(0) + INTERVAL Transition_Time SECOND AS change_time, Offset, Abbreviation 
FROM mysql.time_zone_transition t 
LEFT JOIN mysql.time_zone_transition_type tt ON (
    t.Time_zone_id = tt.Time_zone_id AND 
    t.Transition_type_id = tt.Transition_type_id 
) 
LEFT JOIN mysql.time_zone_name n ON (
    t.Time_zone_id = n.Time_zone_id 
) 
WHERE n.Name = @timezone 
    AND Transition_time < 0 
ORDER BY change_time ASC; 

अपने नमूना तिथि के लिए संशोधित करना, हम इस निकाल सकते हैं :

SET @timezone = "America/Toronto"; 
SET @birthday = -73440000; 

SELECT ('1970-01-01 00:00:00' + INTERVAL @birthday SECOND) + INTERVAL Offset SECOND AS offsetDate 
FROM mysql.time_zone_transition t 
LEFT JOIN mysql.time_zone_transition_type tt ON (
    t.Time_zone_id = tt.Time_zone_id AND 
    t.Transition_type_id = tt.Transition_type_id 
) 
LEFT JOIN mysql.time_zone_name n ON (
    t.Time_zone_id = n.Time_zone_id 
) 
WHERE n.Name = @timezone 
    AND Transition_time < @birthday 
ORDER BY Transition_time DESC 
LIMIT 1; 

चूंकि यह तारीख से पहले हाल ही में संक्रमण चुनता है, यह दिनांकों कि पहली संक्रमण पूर्व में होना के लिए कोई रिकॉर्ड वापस आ जाएगी। यह एक संकेतक के रूप में कार्य करना चाहिए कि आप टेरा incognita में हैं और आपको अपना ऑफसेट बनाना होगा।

आप एक fallback के रूप में पहली संक्रमण समय का उपयोग करना चाहते हैं, तो आप WHERE खंड से Transition_time < @birthday हटाने और ORDER BY खंड के बजाय जोड़ने के लिए, के रूप में आप टिप्पणी में सुझाव दिया जा सकता है।

+0

मैंने सोचा कि यह शुद्ध एसक्यूएल में करना मुश्किल होगा लेकिन यह बहुत बुरा नहीं लग रहा है। मैं कल इसे आजमाउंगा। धन्यवाद! – mpen

+0

ऐसा लगता है कि यह सभी तिथियों के लिए काम करता है, लेकिन मुझे कुछ समायोजन करना पड़ा। सबसे पहले, धारा द्वारा ORDER में 'Transition_time <@ जन्मदिन डीईएससी' डालें और इसे कहां से हटा दें। इससे न्यूल के बजाय 1 9 02 से पहले तिथियों के परिणाम मिल जाएंगे। दूसरा, अगर आप इसे '@@ सत्र के साथ काम करना चाहते हैं।time_zone' के बजाय आप पास करते हैं, तो आपको इसे मैन्युअल रूप से कनेक्ट करने के लिए मैन्युअल रूप से सेट करना होगा, अन्यथा इसमें "सिस्टम" जैसी बेवकूफ कुछ होगी जो कि उपयोगी नहीं है। – mpen

+0

खुशी मैं मदद कर सकता था। यह ज़ोन डेटा शुरू होने से पहले किसी भी तारीख के लिए 0 परिणाम लौटाएगा, यह दर्शाता है कि कोई ज्ञात ऑफ़सेट नहीं है और आपको स्वयं को कुछ बनाना होगा। मैं इसे स्पष्ट करने के लिए उत्तर संपादित करूंगा। – miken32

0

मैंने 1 9 18 (उस टाइमज़ोन से पहले गड़बड़ कर दिया गया है) और 2100 के बीच 200 से अधिक तिथियों के साथ इन कार्यों का परीक्षण किया है, और PHP द्वारा जेनरेट की गई तारीख w/timezones के मुकाबले उनकी तुलना की गई है।वे पूरी तरह से काम करने लगते हैं।

CREATE FUNCTION `dt2ts` (`d` DATETIME) RETURNS BIGINT 
DETERMINISTIC 
BEGIN 
     DECLARE `result` BIGINT; 

     SELECT TIMESTAMPDIFF(SECOND, '1970-01-01 00:00:00', `d`) - Offset INTO `result` 
     FROM mysql.time_zone_transition t 
      LEFT JOIN mysql.time_zone_transition_type tt 
       ON t.Time_zone_id = tt.Time_zone_id AND t.Transition_type_id = tt.Transition_type_id 
      LEFT JOIN mysql.time_zone_name n ON t.Time_zone_id = n.Time_zone_id 
     WHERE n.Name = @@session.time_zone 
     ORDER BY Transition_time <= TIMESTAMPDIFF(SECOND, '1970-01-01 00:00:00', `d`) - Offset DESC, Transition_time DESC 
     LIMIT 1; 


     RETURN `result`; 
END 

फर्क सिर्फ इतना है कि मैं इस और PHP के बीच में पाया गया कि dt2ts('2016-11-06 01:00:00')America/Vancouver जबकि PHP के लिए 1478422800 देता है:

CREATE FUNCTION `ts2dt` (`d` bigint) RETURNS datetime 
DETERMINISTIC 
    BEGIN 
     DECLARE `result` DATETIME; 


     SELECT ('1970-01-01 00:00:00' + INTERVAL `d` SECOND) + INTERVAL Offset SECOND INTO `result` 
     FROM mysql.time_zone_transition t 
     LEFT JOIN mysql.time_zone_transition_type tt ON (
      t.Time_zone_id = tt.Time_zone_id AND 
      t.Transition_type_id = tt.Transition_type_id 
     ) 
     LEFT JOIN mysql.time_zone_name n ON (
      t.Time_zone_id = n.Time_zone_id 
     ) 
     WHERE n.Name = @@session.time_zone 
     ORDER BY Transition_time <= `d` DESC, Transition_time DESC 
     LIMIT 1; 

     RETURN `result`; 
    END 

एक टाइमस्टैम्प में एक datetime करें:

एक datetime में एक टाइमस्टैम्प मुड़ें 1478419200 देता है, हालांकि, दोनों टाइमस्टैम्प 1:00 बजे (डीएसटी स्विच की वजह से) के अनुरूप हैं, इसलिए मुझे लगता है कि कोई जवाब सही है।

एनबी। यदि आपका सत्र टाइमज़ोन सेट नहीं है तो ये फ़ंक्शन null देते हैं। साथ यह सेट करें:

set session time_zone='America/Vancouver'; 
संबंधित मुद्दे