2010-11-13 20 views
21

मैं 12-4-1999 या 1-31-1999 जैसी तारीख को पार्स करने के लिए हास्केल की दिनांक के साथ काम कर रहा हूं। मैंने कोशिश की:हास्केल दिनांक पार्सिंग और स्वरूपण

parseDay :: String -> Day 
parseDay s = readTime defaultTimeLocale "%m%d%Y" s 

और मैं इसे अपने महीनों और दिनों में 1 या 2 के बजाय ठीक दो अंक चाहता है ...

यह करने के लिए उचित तरीका क्या है?

इसके अलावा, मैं इस प्रारूप में अपना दिन प्रिंट करना चाहता हूं: 12/4/1999 हास्केल तरीका क्या है?

सहायता के लिए धन्यवाद।

+1

क्या आपको% m,% d, और% Y के बीच डैश की आवश्यकता नहीं है? – sclv

+0

@AlexBaranosky आप इस प्रश्न का एक अलग जवाब स्वीकार करने पर विचार करना चाहेंगे :) – Ben

उत्तर

-2

यहाँ, कुछ पुराने कोड है कि घर का बना दिनांकों के दो प्रकार के होते हैं सिर्फ YMD, कोई समय या समय-क्षेत्रों, आदि के साथ तारीखों

इससे पता चलता है readDec का उपयोग कर दिनांकों में तार पार्स करने के लिए कैसे। parseDate फ़ंक्शन देखें। readDec, संख्या के साथ, यह प्रमुख रिक्त स्थान (filter की वजह से) या प्रमुख शून्यों के बारे में कोई फर्क नहीं पड़ता, और पार्स पहले गैर-अंकों पर बंद हो जाता है। फिर तिथि के अगले संख्यात्मक क्षेत्र में जाने के लिए tail (गैर अंकों को छोड़ने के लिए) का उपयोग किया गया।

यह आउटपुट के लिए स्वरूपण के कई तरीकों को दिखाता है, लेकिन सबसे लचीला तरीका Text.printf का उपयोग करना है। instance Show LtDate देखें। printf के साथ, कुछ भी संभव है!

import Char 
import Numeric 
import Data.Time.Calendar 
import Data.Time.Clock 
import Text.Printf 
-- ================================================================ 
--      LtDate 
-- ================================================================ 
type Date=(Int,Int,Int) 
data LtDate = LtDate 
    { ltYear :: Int, 
    ltMonth:: Int, 
    ltDay :: Int 
    } 
instance Show LtDate 
    where show d = printf "%4d-%02d-%02d" (ltYear d) (ltMonth d) (ltDay d) 

toLtDate :: Date -> LtDate 
toLtDate (y,m,d)= LtDate y m d 

-- ============================================================= 
--       Date 
-- ============================================================= 
-- | Parse a String mm/dd/yy into tuple (y,m,d) 
-- accepted formats 
-- 
-- @ 
-- 12\/01\/2004 
-- 12\/ 1\' 4 
-- 12-01-99 
-- @ 
parseDate :: String -> Date 
parseDate s = (y,m,d) 
    where [(m,rest) ] = readDec (filter (not . isSpace) s) 
      [(d,rest1)] = readDec (tail rest) 
      [(y, _) ] = parseDate' rest1 

-- | parse the various year formats used by Quicken dates 
parseDate':: String -> [(Int,String)] 
parseDate' (y:ys) = 
    let [(iy,rest)] = readDec ys 
     year=case y of '\''  -> iy + 2000 
        _ -> 
         if iy < 1900 then iy + 1900 else iy 
    in [(year,rest)] 

-- | Note some functions sort by this format 
-- | So be careful when changing it. 
showDate::(Int, Int, Int) -> String 
showDate (y,m,d)= yy ++ '-':mm ++ '-':dd 
    where dd=zpad (show d) 
      mm = zpad (show m) 
      yy = show y 
      zpad [email protected](_:ds') 
      | ds'==[] = '0':ds 
      | otherwise = ds 


-- | from LtDate to Date 
fromLtDate :: LtDate -> Date 
fromLtDate lt = (ltYear lt, ltMonth lt, ltDay lt) 

एक बार जब आप (वाई, एम, डी) है, यह डेटा जोड़तोड़ के लिए एक हास्केल पुस्तकालय प्रकार कन्वर्ट करने के लिए आसान है। एक बार जब आप एचएस पुस्तकालयों के साथ काम कर लेंगे, तो Text.printf का उपयोग डिस्प्ले की तारीख को प्रारूपित करने के लिए किया जा सकता है।

+5

जो हास्यास्पद रूप से जटिल लगता है! एक आसान तरीका होना चाहिए, भगवान –

+0

मेरी मदद करें कृपया एक नजदीकी नज़र डालें, कोड एक उदाहरण था और यह आवश्यक नहीं है: दिनांक 'पर्सडेडेट' को पार्स करने के लिए केवल 4 लाइनों की आवश्यकता है; 'readDec' 3 बार कॉल करें। एक बार तारीख का उपयोग Text.printf' दिखाने के लिए। फ़ाइल लोड करें और यह देखने के लिए इसे अपनी तिथि पर चलाएं कि यह काम करता है, फिर उन 'parseDat'e और 'printf' को देखें। यह पार्सडेट स्पेस को अनदेखा करता है और तारीखों में सेपरेटर '-', या '/' के बारे में परवाह नहीं करता है। यह '55 से 1 9 55, आदि में बदलता है। यह 10 लाइनें ('parseDate'') 'शोडेट', और' से LTDate' और 'डेटा' कथन की आवश्यकता नहीं है। न तो घड़ी और कैलेंडर में शामिल हैं। – frayser

+1

'parseDate' और' parseDate 'को छोड़कर सबकुछ हटाएं, यह इसे आसान लग जाएगा। 'डेटा। खरी' और 'न्यूमेरिक' के लिए शामिल रखें वर्ष पार्सर, 'पार्सडेट' को किसी अन्य कॉल के साथ 'readDec'' में बदला जा सकता है। – frayser

7

हाल ही में, मैं आपकी सभी दिनांक/समय पार्सिंग आवश्यकताओं के लिए strptime पैकेज का उपयोग करने की सलाह दूंगा।

46

आप तिथियों में पढ़ने के लिए Data.Time.Format में फ़ंक्शंस का उपयोग कर सकते हैं। मैंने नीचे एक छोटा सा प्रोग्राम शामिल किया है जो एक प्रारूप में एक तिथि में पढ़ता है और लिखता है कि तारीख दो अलग-अलग प्रारूपों में वापस आती है। एकल-अंक महीनों या दिनों में पढ़ने के लिए,% और प्रारूप विनिर्देशक के बीच एक एकल हाइफ़न (-) रखें।

import Locale 
import Data.Time 
import Data.Time.Format 

main = 
    do 
    let dateString = "26 Jan 2012 10:54 AM" 
    let timeFromString = readTime defaultTimeLocale "%d %b %Y %l:%M %p" dateString :: UTCTime 
    -- Format YYYY/MM/DD HH:MM 
    print $ formatTime defaultTimeLocale "%Y/%m/%d %H:%M" timeFromString 
    -- Format MM/DD/YYYY hh:MM AM/PM 
    print $ formatTime defaultTimeLocale "%m/%d/%Y %I:%M %p" timeFromString 

उत्पादन इस तरह दिखता है:

"2012/01/26 10:54" 
"01/26/2012 10:54 AM" 

Data.Time.Format "समय" पैकेज से उपलब्ध है। यदि आपको एकल-अंक महीनों या दिनों का विश्लेषण करने की आवश्यकता है, तो दूसरे शब्दों में 9-9 -2012 की तिथियां, फिर% और प्रारूप वर्णों के बीच एक एकल हाइफ़न शामिल करें। तो "9 -9-2012" को पार्स करने के लिए आपको प्रारूप स्ट्रिंग "% -d-% - m-% Y" की आवश्यकता होगी।

अगस्त, 2014 के रूप में, लोकेल अब हास्केल 1998 "लोकेल" पैकेज की बजाय "सिस्टम.लोकेल" पैकेज से सबसे अच्छा प्राप्त किया गया है।इसे ध्यान में रखते, अब ऊपर से नमूना कोड पढ़ता है:

import System.Locale 
import Data.Time 
import Data.Time.Format 

main = 
    do 
    let dateString = "26 Jan 2012 10:54 AM" 
    let timeFromString = readTime defaultTimeLocale "%d %b %Y %l:%M %p" dateString :: UTCTime 
    -- Format YYYY/MM/DD HH:MM 
    print $ formatTime defaultTimeLocale "%Y/%m/%d %H:%M" timeFromString 
    -- Format MM/DD/YYYY hh:MM AM/PM 
    print $ formatTime defaultTimeLocale "%m/%d/%Y %I:%M %p" timeFromString 

    -- now for a string with single digit months and days: 
    let dateString = "9-8-2012 10:54 AM" 
    let timeFromString = readTime defaultTimeLocale "%-d-%-m-%Y %l:%M %p" dateString :: UTCTime 
    -- Format YYYY/MM/DD HH:MM 
    print $ formatTime defaultTimeLocale "%Y/%m/%d %H:%M" timeFromString 

उत्पादन अब इस तरह दिखता है:

"2012/01/26 10:54" 
"01/26/2012 10:54 AM" 
"2012/08/09 10:54" 

जुलाई 2017 के रूप में, इसके बाद के संस्करण कोड अब पदावनत parseTime उपयोग करता है। आपको अब parseTimeOrError का उपयोग करने के लिए प्रोत्साहित किया जाता है। कोड हो जाता है:

import Data.Time 

main = 
    do 
    let dateString = "26 Jan 2012 10:54 AM" 
    let timeFromString = parseTimeOrError True defaultTimeLocale "%d %b %Y %l:%M %p" dateString :: UTCTime 
    -- Format YYYY/MM/DD HH:MM 
    print $ formatTime defaultTimeLocale "%Y/%m/%d %H:%M" timeFromString 
    -- Format MM/DD/YYYY hh:MM AM/PM 
    print $ formatTime defaultTimeLocale "%m/%d/%Y %I:%M %p" timeFromString 

    -- now for a string with single digit months and days: 
    let dateString = "9-8-2012 10:54 AM" 
    let timeFromString = parseTimeOrError True defaultTimeLocale "%-d-%-m-%Y %l:%M %p" dateString :: UTCTime 
    -- Format YYYY/MM/DD HH:MM 
    print $ formatTime defaultTimeLocale "%Y/%m/%d %H:%M" timeFromString 

.cabal फ़ाइल से संस्करणों: निर्माण निर्भर करता है: आधार> = 4.9 & & < 4.10, समय> = 1.6.0.1

जिसके अनुसार, इस सवाल का जवाब मिल रहा है हास्केल पैकेज विकसित होने वाली दर को थोड़ी देर तक दांत दिया गया। यह एक बेहतर समाधान की तलाश करने का समय हो सकता है।

+5

आलसी के लिए, यह 'समय' पैकेज में है। – user239558

+1

आदमी! वह% -d चाल दस्तावेज़ में होना चाहिए। – Bzzt

+0

मुझे 'संदिग्ध घटना' डिफ़ॉल्ट टाइममोकेल '' मिलती है, यह 'Data.Time.defaultTimeLocale' या' System.Locale.defaultTimeLocale' है? – peer

9

का प्रयोग% -d और%% d और% मीटर के बजाय -m का मतलब एकल अंक दिन/माह ठीक है, यानी

parseDay :: String -> Day 
parseDay s = readTime defaultTimeLocale "%-m%-d%Y" s 

यह वही किया मतलब sclv सकता है, लेकिन उसकी टिप्पणी कुछ ज़्यादा ही था मेरे लिए गुप्त

+1

+1। मैं इस पर अपने बालों को खींच रहा था और regexes के लिए बारी के बारे में! –

संबंधित मुद्दे