আমি যেমন পরে ব্যাখ্যা করছি, আমি সর্বদা পদ্ধতি TryParse
এবং TryParseExact
পদ্ধতির পক্ষে চাই । এগুলি ব্যবহার করতে কিছুটা ভারী হওয়ায় আমি একটি এক্সটেনশন পদ্ধতি লিখেছি যা পার্সিংকে আরও সহজ করে তোলে:
var dtStr = "2011-03-21 13:26";
DateTime? dt = dtStr.ToDate("yyyy-MM-dd HH:mm");
ইত্যাদি থেকে পৃথক Parse
, ParseExact
এটি একটি ব্যতিক্রম ছুঁড়ে না, এবং আপনাকে মাধ্যমে পরীক্ষা করতে দেয় allows
if (dt.HasValue) { // continue processing } else { // do error handling }
রূপান্তরটি সফল হয়েছিল কিনা (এই ক্ষেত্রে dt
আপনার মাধ্যমে অ্যাক্সেস করতে পারেন এমন একটি মান রয়েছে dt.Value
) বা না (এই ক্ষেত্রে এটি হ'ল null
)।
এটি এমনকি "এলভিস" -অ্যাপেরেটরের মতো মার্জিত শর্টকাটগুলি ব্যবহার করার অনুমতি দেয় ?.
:
int? year = dtStr?.ToDate("yyyy-MM-dd HH:mm")?.Year;
year.HasValue
রূপান্তরটি সফল হয়েছে কিনা তা পরীক্ষা করতে আপনি এখানেও ব্যবহার করতে পারেন এবং এটি যদি সফল না হয় তবে তা year
থাকবে null
, অন্যথায় তারিখের বছরের অংশটি। রূপান্তর ব্যর্থ হলে সেখানে কোনও ব্যতিক্রম ছোঁড়া হয় না।
সমাধান: .ToDate () এক্সটেনশন পদ্ধতি
। নেটফিডেলে এটি চেষ্টা করুন
public static class Extensions
{
// Extension method parsing a date string to a DateTime?
// dateFmt is optional and allows to pass a parsing pattern array
// or one or more patterns passed as string parameters
public static DateTime? ToDate(this string dateTimeStr, params string[] dateFmt)
{
// example: var dt = "2011-03-21 13:26".ToDate(new string[]{"yyyy-MM-dd HH:mm",
// "M/d/yyyy h:mm:ss tt"});
// or simpler:
// var dt = "2011-03-21 13:26".ToDate("yyyy-MM-dd HH:mm", "M/d/yyyy h:mm:ss tt");
const DateTimeStyles style = DateTimeStyles.AllowWhiteSpaces;
if (dateFmt == null)
{
var dateInfo = System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat;
dateFmt=dateInfo.GetAllDateTimePatterns();
}
// Commented out below because it can be done shorter as shown below.
// For older C# versions (older than C#7) you need it like that:
// DateTime? result = null;
// DateTime dt;
// if (DateTime.TryParseExact(dateTimeStr, dateFmt,
// CultureInfo.InvariantCulture, style, out dt)) result = dt;
// In C#7 and above, we can simply write:
var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
style, out var dt) ? dt : null as DateTime?;
return result;
}
}
কোড সম্পর্কে কিছু তথ্য
আপনি ভাবতে পারেন, কেন আমি InvariantCulture
কলিং ব্যবহার করেছি TryParseExact
: এটি ফাংশনটিকে সর্বদা একইভাবে বিন্যাসের আচরণ করতে বাধ্য করা হয় (অন্যথায় উদাহরণস্বরূপ "।" এটি যখন গ্রুপ বিভাজক হয় তখন ইংরেজিতে দশমিক বিভাজক হিসাবে ব্যাখ্যা করা যেতে পারে বা তারিখ বিভাজক হয় জার্মান)। প্রত্যাহার করুন আমরা সংস্কৃতি ভিত্তিক ফর্ম্যাট স্ট্রিংগুলি কয়েক লাইনের আগে জিজ্ঞাসা করেছি যাতে এটি ঠিক আছে।
আপডেট: .ToDate()
(প্যারামিটার ব্যতীত) এখন থ্রেডের বর্তমান সংস্কৃতির সমস্ত সাধারণ তারিখ / সময় নিদর্শনগুলিতে ডিফল্ট।
নোট করুন যে আমাদের প্রয়োজন result
এবং dt
একসাথে দরকার , কারণ TryParseExact
ব্যবহার করার অনুমতি দেয় না DateTime?
, যা আমরা ফেরত যেতে চাইছি। ইন সি # সংস্করণ 7 আপনি প্রক্রিয়া সহজ পারে ToDate
নিম্নরূপ ফাংশন একটি বিট:
// in C#7 only: "DateTime dt;" - no longer required, declare implicitly
if (DateTime.TryParseExact(dateTimeStr, dateFmt,
CultureInfo.InvariantCulture, style, out var dt)) result = dt;
অথবা, আপনি যদি এটি আরও ছোট করে পছন্দ করেন:
// in C#7 only: Declaration of result as a "one-liner" ;-)
var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
style, out var dt) ? dt : null as DateTime?;
যে ক্ষেত্রে আপনার দুটি ঘোষণাপত্রের DateTime? result = null;
এবং কোনও প্রয়োজন নেই DateTime dt;
- আপনি কোডের এক লাইনে এটি করতে পারেন। ( আপনি যদি এটি পছন্দ করেন তবে out DateTime dt
পরিবর্তে এটি লেখারও অনুমতি দেওয়া হবে out var dt
)।
আমি params
কীওয়ার্ডটি ব্যবহার করে কোডটি আরও সরল করে দিয়েছি : এখন আপনার আর 2 এনডি ওভারলোডেড পদ্ধতি দরকার নেই ।
ব্যবহারের উদাহরণ
var dtStr="2011-03-21 13:26";
var dt=dtStr.ToDate("yyyy-MM-dd HH:mm");
if (dt.HasValue)
{
Console.WriteLine("Successful!");
// ... dt.Value now contains the converted DateTime ...
}
else
{
Console.WriteLine("Invalid date format!");
}
আপনি দেখতে পাচ্ছেন, এই উদাহরণটি dt.HasValue
রূপান্তরটি সফল হয়েছে কি না তা দেখার জন্য কেবল অনুসন্ধান করে। অতিরিক্ত বোনাস হিসাবে, ট্রাইপার্সি এক্স্যাক্ট কঠোরভাবে নির্দিষ্ট করতে দেয় DateTimeStyles
যাতে আপনি সঠিক তারিখ / সময় স্ট্রিং পেরিয়ে গেছে কিনা তা ঠিক জানেন know
ব্যবহারের আরও উদাহরণ
ওভারলোডেড ফাংশন আপনাকে এখানে যেমন দেখানো হয়েছে ( সরাসরি এটি সমর্থন করে) যেমন পার্সিং / রূপান্তর করার জন্য ব্যবহৃত বৈধ বিন্যাসগুলির একটি অ্যারে পাস করার অনুমতি দেয় , যেমনTryParseExact
string[] dateFmt = {"M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt",
"MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss",
"M/d/yyyy hh:mm tt", "M/d/yyyy hh tt",
"M/d/yyyy h:mm", "M/d/yyyy h:mm",
"MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm"};
var dtStr="5/1/2009 6:32 PM";
var dt=dtStr.ToDate(dateFmt);
আপনার যদি কয়েকটি কয়েকটি টেম্পলেট নিদর্শন থাকে তবে আপনি এটিও লিখতে পারেন:
var dateStr = "2011-03-21 13:26";
var dt = dateStr.ToDate("yyyy-MM-dd HH:mm", "M/d/yyyy h:mm:ss tt");
উন্নত উদাহরণ
আপনি ??
ব্যর্থ-নিরাপদ বিন্যাসে ডিফল্ট করতে অপারেটরটি ব্যবহার করতে পারেন , যেমন
var dtStr = "2017-12-30 11:37:00";
var dt = (dtStr.ToDate()) ?? dtStr.ToDate("yyyy-MM-dd HH:mm:ss");
এই ক্ষেত্রে, এটি .ToDate()
সাধারণ স্থানীয় সংস্কৃতি তারিখের ফর্ম্যাটগুলি ব্যবহার করবে এবং যদি এই সমস্ত ব্যর্থ হয়, তবে এটি আইএসও স্ট্যান্ডার্ড ফর্ম্যাটটিকে "yyyy-MM-dd HH:mm:ss"
ফ্যালব্যাক হিসাবে ব্যবহার করার চেষ্টা করবে । এইভাবে, এক্সটেনশন ফাংশনটি সহজেই বিভিন্ন ফ্যালব্যাক ফর্ম্যাটগুলিকে "চেইন" করতে দেয়।
এমনকি আপনি লিনকিউতে এক্সটেনশনটি ব্যবহার করতে পারেন, এটি ব্যবহার করে দেখুন (এটি উপরের নেটফিডেলে রয়েছে):
var patterns=new[] { "dd-MM-yyyy", "dd.MM.yyyy" };
(new[] { "15-01-2019", "15.01.2019" }).Select(s => s.ToDate(patterns)).Dump();
যা নমুনাগুলি ব্যবহার করে ফ্লাইটে অ্যারেতে তারিখগুলি রূপান্তর করবে এবং কনসোলে ডাম্প করবে।
ট্রাইপার্সেক্স্যাক্ট সম্পর্কে কিছু পটভূমি
শেষ অবধি, ব্যাকগ্রাউন্ড সম্পর্কে কিছু মন্তব্য এখানে দেওয়া হয়েছে (উদাহরণস্বরূপ যে কারণে আমি এটি এভাবে লিখেছি):
আমি এই এক্সটেনশন পদ্ধতিতে ট্রাই পার্সেক্স্যাক্টকে প্রাধান্য দিচ্ছি , কারণ আপনি ব্যতিক্রম হ্যান্ডলিং এড়ান - আপনি পার্সের পরিবর্তে ট্রাইপার্স কেন ব্যবহার করবেন সে ব্যতিক্রম সম্পর্কে আপনি এরিক লিপার্টের নিবন্ধে পড়তে পারেন , আমি তাকে এই বিষয়টির উদ্ধৃতি দিয়েছি: 2)
এই দুর্ভাগ্যজনক ডিজাইনের সিদ্ধান্ত 1) [টিকা: পার্স পদ্ধতিটি একটি ব্যতিক্রম ছুঁড়তে দিন] এতটাই উদ্বেগজনক ছিল যে অবশ্যই
ফ্রেমওয়ার্কস দলটি ট্রাইপার্সাকে কার্যকর করেছিল এর পরেই যা সঠিক কাজ করে does
এটা আছে, কিন্তু TryParse
এবং TryParseExact
উভয় এখনো অনেক কম ব্যবহার আরামদায়ক আছেন: তারা একটি হিসাবে একটি uninitialized ভেরিয়েবল ব্যবহার করার জন্য আপনি বাধ্য out
পরামিতি, যা nullable হবে না এবং আপনি রূপান্তর করছি যখন আপনি বুলিয়ান ফেরত মান নির্ণয় করা প্রয়োজন - পারেন আপনি if
অবিলম্বে একটি বিবৃতি ব্যবহার করতে বা আপনাকে অতিরিক্ত বুলিয়ান ভেরিয়েবলে রিটার্ন মান সংরক্ষণ করতে হবে যাতে আপনি পরে চেকটি করতে সক্ষম হবেন able এবং আপনি রূপান্তরটি সফল হয়েছে কিনা তা জেনেও কেবল টার্গেট ভেরিয়েবলটি ব্যবহার করতে পারবেন না।
বেশিরভাগ ক্ষেত্রে আপনি কেবল জানতে চান যে রূপান্তরটি সফল হয়েছিল কিনা (এবং অবশ্যই এটি সফল হলে মানটি) , তাই একটি অযোগ্য লক্ষ্য পরিবর্তনশীল যা সমস্ত তথ্য রাখে তা আকাঙ্ক্ষিত এবং আরও মার্জিত হবে - কারণ পুরো তথ্যটি হ'ল কেবলমাত্র এক জায়গায় সংরক্ষণ করা হয়েছে: এটি ধারাবাহিক এবং সহজেই ব্যবহারযোগ্য এবং ত্রুটি-প্রবণতাও কম।
আমি যে এক্সটেনশন পদ্ধতিটি লিখেছি তা হুবহু এটি করে (এটি আপনাকে দেখায় যে আপনি প্রতিবার কী ধরণের কোড লিখতে হবে যদি আপনি এটি ব্যবহার না করে থাকেন)।
আমি বিশ্বাস করি এর সুবিধাটি .ToDate(strDateFormat)
হ'ল এটি সহজ এবং পরিষ্কার দেখায় - মূলটি যতটা সহজ DateTime.Parse
বলে মনে করা হত - তবে রূপান্তরটি সফল হয়েছিল কিনা তা পরীক্ষা করার ক্ষমতা সহ এবং ব্যতিক্রম ছুঁড়ে না ফেলে।
1) এখানে বোঝানো হচ্ছে ব্যতিক্রম হ্যান্ডলিং (অর্থাত্ একটি try { ... } catch(Exception ex) { ...}
ব্লক) - যা আপনি যখন পার্স ব্যবহার করছেন তখন প্রয়োজনীয় কারণ এটি যদি কোনও অবৈধ স্ট্রিংকে বিশ্লেষণ করে তবে ব্যতিক্রম হয় - কেবল এই ক্ষেত্রে অপ্রয়োজনীয় নয় তবে বিরক্তিকর, এবং আপনার কোড জটিল। আমার দেওয়া কোডের নমুনাটি প্রদর্শিত হচ্ছে বলে ট্রিপ পার্সে এগুলি এড়িয়ে চলে।
২) এরিক লিপার্ট স্ট্যাকওভারফ্লো একজন বিখ্যাত সহকর্মী এবং মাইক্রোসফ্টে সি # সংকলক টিমের প্রধান বিকাশকারী হিসাবে কয়েক বছর ধরে কাজ করছিলেন।