মোবাইল ডেভেলপমেন্টে তারিখ এবং সময় — মোবাইল ইঞ্জিনিয়ারিংয়ের মূল বিষয়গুলির মধ্যে একটি। iOS DateFormatter এবং ISO8601DateFormatter ব্যবহার করে, Android java.time থেকে DateTimeFormatter এবং LocalDate ব্যবহার করে। Android Developer Docs অনুসারে, তারিখ এবং সময় ফরম্যাট করার জন্য সঠিক মোবাইল API নির্বাচন সরাসরি বিভিন্ন সময় অঞ্চলে কর্মক্ষমতা এবং সঠিক প্রদর্শনকে প্রভাবিত করে।
মূল বিষয়
iOS-এ, তারিখ এবং সময় ঐতিহ্যগতভাবে Foundation-এর DateFormatter-এর মাধ্যমে ফরম্যাট করা হয়। এই ক্লাসটি নির্দিষ্ট প্যাটার্ন, লোকেল এবং সময় অঞ্চল ব্যবহার করে Date-কে স্ট্রিং-এ এবং ফিরে রূপান্তর করে। DateFormatter-এর মূল সমস্যা — এটি থ্রেড-সেফ নয় এবং ধীরে তৈরি হয়, তাই মোবাইল কোডে ইনস্ট্যান্সগুলি বাধ্যতামূলকভাবে ক্যাশে করতে হয়। iOS-এ মোবাইল ডেভেলপমেন্টে তারিখের সঠিক ফরম্যাটার প্রয়োজন।
DateFormatter তৈরি করতে প্রায় 1 মিলিসেকেন্ড সময় লাগে কারণ dateFormat প্যাটার্ন পার্স করা, লোকেল লোড করা এবং সময় অঞ্চল নির্ধারণ করতে হয়। শত শত তারিখের তালিকা ফরম্যাট করার সময়, বারবার তৈরি করলে UI-তে লক্ষণীয় ব্যবধান দেখা দেয়। সমাধান — পুরো স্ক্রিনের জন্য একবার ফরম্যাটার তৈরি করুন এবং পুনরায় ব্যবহার করুন। মাল্টিথ্রেডেড অ্যাক্সেসের জন্য, DispatchQueue-এর মাধ্যমে সিঙ্ক্রোনাইজেশন ব্যবহার করুন।
import Foundation
// ক্যাশে করা DateFormatter — একবার তৈরি হয়
private let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy HH:mm"
formatter.locale = Locale(identifier: "ru_RU")
formatter.timeZone = TimeZone(identifier: "Europe/Moscow")
return formatter
}()
// ISO8601DateFormatter — হালকা বিকল্প
private let isoFormatter: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return formatter
}()
let now = Date()
let formattedDate = dateFormatter.string(from: now)
// "01.07.2026 14:30"
let isoDate = isoFormatter.string(from: now)
// "2026-07-01T14:30:00.000Z"
ISO 8601 ফরম্যাটের জন্য, ISO8601DateFormatter ব্যবহার করুন — এটির প্যাটার্ন নির্দিষ্ট করার প্রয়োজন নেই এবং এটি DateFormatter-এর চেয়ে দ্রুত কাজ করে। iOS 10+-এ, এই ক্লাসটি সার্ভার তারিখের সাথে কাজ করার জন্য পছন্দনীয়। পুরনো ফরম্যাটের জন্য, DateFormatter রাখুন তবে ইনস্ট্যান্সটিকে স্ট্যাটিক প্রপার্টি বা সিঙ্গলটন হিসেবে ক্যাশে করতে ভুলবেন না।
Android-এ, তারিখ এবং সময় java.time প্যাকেজের মাধ্যমে প্রক্রিয়া করা হয়, যা API 26 থেকে উপলব্ধ। প্রধান ক্লাস: LocalDate (শুধু তারিখ), LocalTime (শুধু সময়), LocalDateTime (সময় অঞ্চল ছাড়া তারিখ এবং সময়) এবং ZonedDateTime (সময় অঞ্চল সহ)। DateTimeFormatter — Android মোবাইল প্ল্যাটফর্মের জন্য থ্রেড-সেফ ফরম্যাটার। মোবাইল অ্যাপ্লিকেশনে তারিখ কর্মক্ষমতা হ্রাস ছাড়াই DateTimeFormatter এবং LocalDate-এর মাধ্যমে ফরম্যাট করা হয়।
LocalDate সময় ছাড়া তারিখ সংরক্ষণ করে — জন্মদিনের জন্য আদর্শ। ZonedDateTime সময় অঞ্চল সহ সম্পূর্ণ তথ্য সংরক্ষণ করে। DateTimeFormatter পূর্বনির্ধারিত প্যাটার্ন (ISO_LOCAL_DATE, ISO_DATE_TIME) এবং ofPattern-এর মাধ্যমে কাস্টম প্যাটার্ন সমর্থন করে। সমস্ত java.time ক্লাস অপরিবর্তনীয় এবং থ্রেড-সেফ, যা একাধিক থ্রেডে কাজ করার সময় রেস কন্ডিশন দূর করে।
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.ZoneId
// বর্তমান তারিখ তৈরি এবং ফরম্যাট করা
val today = LocalDate.now()
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
val formatted = today.format(formatter)
// সময় অঞ্চলের সাথে কাজ করা
val utcTime = ZonedDateTime.now(ZoneId.of("UTC"))
val moscowTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/Moscow"))
DateTimeFormatter SimpleDateFormat-এর তুলনায় উল্লেখযোগ্যভাবে বেশি কার্যকর কারণ এটি প্রতিটি কলেই প্যাটার্ন পার্স করে না। ক্লাস বা কম্প্যানিয়ন অবজেক্ট স্তরে ফরম্যাটার ধ্রুবক তৈরি করার পরামর্শ দেওয়া হয়। Unix Timestamp রূপান্তর করতে, Instant.ofEpochSecond ব্যবহার করুন, তারপর সময় অঞ্চলের মাধ্যমে LocalDateTime বা ZonedDateTime-এ রূপান্তর করুন।
ব্যবহারকারীর স্ক্রিনে সঠিক তারিখ এবং সময় সময় অঞ্চলগুলির সঠিক প্রক্রিয়াকরণের উপর নির্ভর করে। Android-এর জন্য মোবাইল ডেভেলপমেন্টে তারিখ এবং সময়ের জন্য ডিভাইসের সময় অঞ্চল বিবেচনা করা প্রয়োজন। সোনার নিয়ম: সময় UTC-তে সংরক্ষণ করুন, শুধুমাত্র প্রদর্শনের জন্য স্থানীয় সময় অঞ্চলে রূপান্তর করুন। iOS Foundation থেকে TimeZone প্রদান করে, Android java.time থেকে ZoneId প্রদান করে। মোবাইল প্ল্যাটফর্মের জন্য উভয় API ডিভাইসের বর্তমান সময় অঞ্চল স্বয়ংক্রিয়ভাবে সনাক্তকরণ সমর্থন করে। মোবাইল অ্যাপ্লিকেশনে তারিখ ZoneId এবং TimeZone-এর উপর নির্ভর করে।
ডেলাইট সেভিং টাইম অস্পষ্টতা তৈরি করে: সময়ের একটি মুহূর্ত দুটি ভিন্ন স্থানীয় ঘড়ি দ্বারা উপস্থাপিত হতে পারে। java.time এবং Foundation স্বয়ংক্রিয়ভাবে DST পরিচালনা করে। IANA আইডেন্টিফায়ার (Europe/Moscow, America/New_York) ব্যবহার করুন, সংক্ষিপ্ত রূপ (MSK, EST) নয় — সংক্ষিপ্ত রূপগুলি অস্পষ্ট এবং ডেলাইট সেভিং টাইম রূপান্তর উপেক্ষা করে।
import Foundation
// UTC-কে iOS-এ স্থানীয় সময়ে রূপান্তর
func formatToLocalTime(utcDate: Date, timeZoneId: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy HH:mm"
formatter.timeZone = TimeZone(identifier: timeZoneId)
return formatter.string(from: utcDate)
}
// ডিভাইসের সময় অঞ্চল নির্ধারণ
let localTimeZone = TimeZone.current
let isDST = localTimeZone.isDaylightSavingTime()
let secondsFromGMT = localTimeZone.secondsFromGMT()
Android-এ, ডিভাইসের সময় অঞ্চল পেতে ZoneId.systemDefault() ব্যবহার করুন। UTC-কে স্থানীয় সময়ে রূপান্তর করার সময়, ZoneOffset.UTC সহ ZonedDateTime তৈরি করুন এবং withZoneSameInstant প্রয়োগ করুন। java.time ছাড়া পুরনো API-র জন্য, TimeZone.getDefault() এবং Calendar ব্যবহার করুন — তবে সরাসরি ThreeTenABP যুক্ত করা ভাল।
import java.time.Instant
import java.time.ZonedDateTime
import java.time.ZoneId
// Unix Timestamp-কে স্থানীয় সময়ে রূপান্তর করুন
fun toLocalDisplay(unixSeconds: Long): String {
val instant = Instant.ofEpochSecond(unixSeconds)
val local = instant.atZone(ZoneId.systemDefault())
return local.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"))
}
ThreeTenABP — একটি অ্যাডাপ্টার লাইব্রেরি যা java.time-কে Android API 26-এর নিচে পোর্ট করে। এটি একই ক্লাস প্রদান করে: LocalDate, LocalTime, ZonedDateTime, DateTimeFormatter, Instant। যদি অ্যাপ্লিকেশন Android 5 বা 6 (API 21-25) সমর্থন করে, তাহলে ThreeTenABP হল পুরনো Calendar-এ স্যুইচ না করে আধুনিক মোবাইল API ব্যবহার করার একমাত্র উপায়। পুরনো ডিভাইসের জন্য মোবাইল ডেভেলপমেন্টে তারিখ এবং সময় এই লাইব্রেরির মাধ্যমে বাস্তবায়িত হয়। পুরনো ডিভাইসের জন্য, তারিখ এবং সময় ThreeTenABP-এর মাধ্যমে বাস্তবায়িত হয়।
লাইব্রেরিটির Application.onCreate() মেথডে AndroidThreeTen.init() কল করে আরম্ভ করার প্রয়োজন হয়। এটি assets থেকে সময় অঞ্চল ডেটা লোড করে। আরম্ভ করার পরে, API সম্পূর্ণরূপে java.time-এর মতো — API 26+ এবং API 21+-এর জন্য কোড একই হবে। লাইব্রেরির আকার প্রায় 400 KB, যা বেশিরভাগ মোবাইল অ্যাপ্লিকেশনের জন্য গ্রহণযোগ্য।
import org.threeten.bp.LocalDate
import org.threeten.bp.format.DateTimeFormatter
// Application-এ আরম্ভ
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}
// API java.time-এর মতো
val today = LocalDate.now()
val formatted = today.format(DateTimeFormatter.ISO_LOCAL_DATE)
আধুনিক ডিভাইসে ThreeTenABP-এর কর্মক্ষমতা মূল java.time-এর সাথে তুলনীয়। পুরনো ডিভাইসে, সময় অঞ্চল ডেটা লোড করার কারণে প্রথম কলটিতে বিলম্ব হতে পারে। Calendar থেকে ThreeTenABP-তে বিদ্যমান কোড ধীরে ধীরে মাইগ্রেট করুন: নতুন মডিউলে Date এবং Calendar-কে Instant এবং LocalDate দিয়ে প্রতিস্থাপন করুন, পুরনো কোড অপরিবর্তিত রেখে দিন।
Unix Timestamp — 1 জানুয়ারি 1970 00:00 UTC থেকে অতিক্রান্ত সেকেন্ডের সংখ্যা। এটি সার্ভার এবং ক্লায়েন্টের মধ্যে সময় সংরক্ষণ এবং বিনিময়ের জন্য একটি সার্বজনীন ফরম্যাট। তবে, ব্যবহারকারীর সেটিংসের কারণে ডিভাইসের সময় প্রকৃত সময় থেকে ভিন্ন হতে পারে। সিঙ্ক্রোনাইজেশনের জন্য NTP ব্যবহার করা হয় — UDP-এর মাধ্যমে নির্ভুল সময় প্রোটোকল। Unix Timestamp হল ফরম্যাট যেখানে সার্ভারে তারিখ এবং সময় সংরক্ষণ করা হয়।
iOS-এ Date().timeIntervalSince1970 1970 থেকে সেকেন্ড রিটার্ন করে। Android-এ System.currentTimeMillis() মিলিসেকেন্ড রিটার্ন করে। নির্ভুলতার জন্য, NTP ব্যবহার করুন: iOS-এর জন্য TrueTime লাইব্রেরি এবং Android-এর জন্য AndroidNtp NTP সার্ভারে অনুরোধ পাঠায় এবং সময় অফসেট গণনা করে। লোকাল নেটওয়ার্কে NTP নির্ভুলতা 1-10 ms এবং ইন্টারনেটের মাধ্যমে 10-100 ms।
import Foundation
// iOS-এ Unix Timestamp প্রাপ্তি
let seconds = Date().timeIntervalSince1970
let milliseconds = Int64(seconds * 1000)
// TrueTime-এর সাথে NTP সিঙ্ক্রোনাইজেশন
TrueTime.shared.start { result in
switch result {
case .success:
let ntpTime = TrueTime.shared.now()
print("নির্ভুল সময়: \(ntpTime)")
case .failure(let error):
print("NTP ত্রুটি: \(error)")
}
}
মোবাইল অ্যাপ্লিকেশনে সিঙ্ক্রোনাইজেশন ছাড়া, ত্রুটি সম্ভব: ভুল ইভেন্ট টাইমস্ট্যাম্প, সার্ভারের সাথে ডিসিঙ্ক্রোনাইজেশন। মোবাইল ডেভেলপমেন্টে সময় অ্যাপ্লিকেশন শুরু হওয়ার সময় একবার NTP-এর মাধ্যমে সিঙ্ক্রোনাইজ করা হয়, তারপরে গণনাকৃত অফসেট ব্যবহার করা হয়। নির্ভুলতার জন্য গুরুত্বপূর্ণ মোবাইল অ্যাপ্লিকেশনের (অর্থ, লজিস্টিকস) জন্য, সার্ভারে ডেটা পাঠানোর আগে NTP প্রোটোকল বাধ্যতামূলক।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
DateFormatter প্রতিবার ইনস্ট্যান্স তৈরি করার সময় ফরম্যাটিং প্যাটার্ন পার্স করে, লোকেল লোড করে এবং সময় অঞ্চল নির্ধারণ করে। ফরম্যাটারটিকে স্ট্যাটিক কনস্ট্যান্ট হিসেবে ক্যাশে করুন বা ISO 8601-এর জন্য ISO8601DateFormatter ব্যবহার করুন — এটি হালকা এবং দ্রুত।
java.time প্যাকেজ থেকে DateTimeFormatter — থ্রেড-সেফ এবং কার্যকর। API 26 থেকে উপলব্ধ। পুরনো সংস্করণের জন্য, ThreeTenABP ব্যবহার করুন যা অভিন্ন API প্রদান করে।
ThreeTenABP যুক্ত করুন — Android API 21+-এর জন্য java.time-এর ব্যাকপোর্ট। Application.onCreate()-এ AndroidThreeTen.init()-এর মাধ্যমে আরম্ভ করুন। API সম্পূর্ণরূপে মূল java.time-এর মতো।
হ্যাঁ, সার্ভার এবং স্থানীয় ডাটাবেসে সময় UTC-তে সংরক্ষণ করুন। শুধুমাত্র প্রদর্শনের পর্যায়ে ব্যবহারকারীর স্থানীয় সময় অঞ্চলে রূপান্তর করুন। এটি সময় অঞ্চল পরিবর্তন বা ভ্রমণের সময় ত্রুটিগুলি দূর করে।
Date().timeIntervalSince1970 1 জানুয়ারি 1970 থেকে সেকেন্ডের সংখ্যা রিটার্ন করে। মিলিসেকেন্ডের জন্য, 1000 দিয়ে গুণ করুন এবং Int64-তে রূপান্তর করুন। নির্ভুল সিঙ্ক্রোনাইজেশনের জন্য, NTP সার্ভারের সাথে TrueTime লাইব্রেরি ব্যবহার করুন।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।