Modern Java
The Modern Date and Time API
You are viewing a free preview lesson.
Lesson Overview
Date এবং time নিয়ে কাজ দেখতে simple মনে হলেও software engineering-এ এটি surprisingly difficult একটি area।
Consider:
2026-08-08 10:00
এই value দেখে আমরা এখনো জানি না:
10:00 কোন time zone-এর?
Tallinn?
Dhaka?
London?
UTC?
আরেকটি example:
A subscription expires after 30 days.
এখানে প্রশ্ন আসতে পারে:
30 calendar days?
নাকি exactly 720 hours?
আর:
A meeting is at 10:00 Europe/Tallinn.
Daylight Saving Time change হলে UTC time কী হবে?
এই সমস্যাগুলো handle করার জন্য modern Java provides:
java.time
package।
এই lesson-এ আমরা শিখব:
LocalDateLocalTimeLocalDateTimeInstantZoneIdZonedDateTimeDurationPeriodDateTimeFormatter- Date/time creation
- Date/time arithmetic
- Date/time comparison
- Parsing
- Formatting
- Time-zone conversion
LocalDateTimeএবংInstant-এর difference- User-facing time বনাম system timestamp
- Daylight Saving Time intuition
- Common date/time mistakes
- Backend systems-এ practical date/time strategy
Why Date and Time Is Difficult
একটি timestamp শুধু:
year
month
day
hour
minute
second
নয়।
Real-world time-এর সাথে জড়িত:
Time zone
UTC offset
Daylight Saving Time
Calendar rules
Leap years
Different month lengths
Human calendar semantics
Machine timestamp semantics
তাই date/time code design করার সময় type selection খুব important।
The java.time Package
Modern Java date/time API-এর classes থাকে:
java.time
package-এ।
Common imports:
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.Duration;
import java.time.Period;
import java.time.format.DateTimeFormatter;
The Most Important Rule
সব date/time value এক ধরনের নয়।
Different problems-এর জন্য different types আছে।
Mental model:
Date only
→ LocalDate
Time only
→ LocalTime
Date + time, but no time zone
→ LocalDateTime
Exact point on global timeline
→ Instant
Date + time + time-zone rules
→ ZonedDateTime
Machine-style elapsed time
→ Duration
Calendar-style elapsed time
→ Period
এই mapping clear থাকলে date/time design অনেক সহজ হয়।
LocalDate
LocalDate represent করে:
year
month
day
কিন্তু এতে নেই:
time
time zone
UTC offset
Example:
LocalDate date =
LocalDate.of(
2026,
8,
8
);
Represents:
2026-08-08
When LocalDate Is Appropriate
Examples:
Birthday
Course start date
Invoice due date
Holiday date
Subscription renewal calendar date
যেখানে exact time-of-day important নয়।
Current Date
LocalDate today =
LocalDate.now();
এটি current system/default time zone অনুযায়ী date দেয়।
Backend code-এ default zone blindly use করার আগে application requirement বুঝতে হবে।
Specific Zone-এর Current Date
LocalDate todayInTallinn =
LocalDate.now(
ZoneId.of(
"Europe/Tallinn"
)
);
এখন date explicitly Tallinn time-zone rules অনুযায়ী calculate হবে।
LocalDate Is Immutable
LocalDate date =
LocalDate.of(
2026,
8,
8
);
Then:
date.plusDays(
5
);
original date modify করে না।
Need:
LocalDate later =
date.plusDays(
5
);
Important Immutability Pattern
Wrong expectation:
date.plusDays(
5
);
System.out.println(
date
);
date unchanged থাকবে।
Correct:
date =
date.plusDays(
5
);
যদি variable reassign করতে চান।
LocalDate Arithmetic
LocalDate date =
LocalDate.of(
2026,
8,
8
);
Add days:
LocalDate tomorrow =
date.plusDays(
1
);
Add weeks:
LocalDate nextWeek =
date.plusWeeks(
1
);
Add months:
LocalDate nextMonth =
date.plusMonths(
1
);
Add years:
LocalDate nextYear =
date.plusYears(
1
);
Subtracting
LocalDate yesterday =
date.minusDays(
1
);
Also:
minusWeeks(...)
minusMonths(...)
minusYears(...)
Calendar Arithmetic Handles Month Rules
Suppose:
LocalDate date =
LocalDate.of(
2026,
1,
31
);
Then:
date.plusMonths(
1
);
Java applies calendar rules rather than pretending every month has 31 days।
এ ধরনের logic manually milliseconds দিয়ে করা উচিত নয়।
Accessing Date Parts
int year =
date.getYear();
Month:
Month month =
date.getMonth();
Month number:
int month =
date.getMonthValue();
Day:
int day =
date.getDayOfMonth();
Day of week:
DayOfWeek dayOfWeek =
date.getDayOfWeek();
Comparing LocalDate
date.isBefore(
anotherDate
);
date.isAfter(
anotherDate
);
date.isEqual(
anotherDate
);
Example
if (
dueDate.isBefore(
today
)
) {
System.out.println(
"Overdue"
);
}
LocalTime
LocalTime represent করে:
hour
minute
second
nanosecond
কিন্তু এতে date বা time zone নেই।
Example:
LocalTime time =
LocalTime.of(
14,
30
);
Represents:
14:30
When LocalTime Is Useful
Examples:
Store opens at 09:00
Daily class begins at 18:30
Reminder should run at 08:00 local time
যেখানে time-of-day important কিন্তু specific date নয়।
Current Time
LocalTime now =
LocalTime.now();
Specific zone:
LocalTime tallinnTime =
LocalTime.now(
ZoneId.of(
"Europe/Tallinn"
)
);
Time Arithmetic
LocalTime start =
LocalTime.of(
10,
0
);
Add 90 minutes:
LocalTime end =
start.plusMinutes(
90
);
Result:
11:30
LocalDateTime
LocalDateTime combines:
LocalDate
+
LocalTime
Example:
LocalDateTime value =
LocalDateTime.of(
2026,
8,
8,
14,
30
);
Represents:
2026-08-08T14:30
Critical: LocalDateTime Has No Time Zone
This is one of the most important concepts in this lesson।
LocalDateTime
contains:
date
time
but does not contain:
time zone
UTC offset
So:
2026-08-08 14:30
by itself is not an exact global moment।
Why Not?
Because:
14:30 in Tallinn
and:
14:30 in Dhaka
occur at different points on the global timeline।
Same wall-clock time।
Different real moment।
When LocalDateTime Is Appropriate
Use it when business meaning genuinely does not yet include a time zone।
Example:
A user entered:
2026-09-01 at 10:00
but zone is stored separately.
Then:
LocalDateTime localDateTime
ZoneId zone
together define the intended moment।
Dangerous Use of LocalDateTime
Suppose database stores:
created_at = 2026-08-08 10:30
without any agreement on time zone।
Later one service assumes UTC।
Another assumes Tallinn।
Now same stored value means two different moments।
For system timestamps:
createdAt
updatedAt
processedAt
an Instant is often more appropriate।
Instant
Instant represent করে global timeline-এর একটি exact point।
Conceptually:
one unambiguous moment
Example:
Instant now =
Instant.now();
Why Instant Is Important
Suppose event happened:
Tallinn:
2026-08-08 20:00
Dhaka:
2026-08-08 23:00
These different local clock representations can refer to the same global instant।
Instant stores the global moment rather than local wall-clock representation।
UTC Mental Model
Instant is naturally represented relative to UTC timeline।
Example textual representation may look like:
2026-08-08T17:00:00Z
Z indicates:
UTC
Common Backend Use Cases for Instant
Excellent for:
createdAt
updatedAt
eventReceivedAt
paymentProcessedAt
requestTimestamp
auditTimestamp
tokenIssuedAt
tokenExpiresAt
where requirement is:
Exactly when did this happen?
Comparing Instants
instant.isBefore(
anotherInstant
);
instant.isAfter(
anotherInstant
);
Add Time to Instant
Instant expiresAt =
issuedAt.plus(
Duration.ofHours(
24
)
);
Now semantics are:
exactly 24 hours later
ZoneId
ZoneId represents a geographic time-zone ruleset।
Example:
ZoneId tallinn =
ZoneId.of(
"Europe/Tallinn"
);
Another:
ZoneId dhaka =
ZoneId.of(
"Asia/Dhaka"
);
Why Use Region-Based Zone IDs?
Prefer:
Europe/Tallinn
Asia/Dhaka
Europe/London
America/New_York
over manually assuming:
UTC+2
UTC+3
for human locations।
Why?
Because a location's offset can change according to time-zone rules, including Daylight Saving Time।
Offset Is Not the Same as Time Zone
An offset looks like:
+03:00
A zone is:
Europe/Tallinn
Europe/Tallinn includes rules that determine which offset applies at a specific date।
So:
ZoneId
carries richer semantics than a fixed offset।
ZonedDateTime
ZonedDateTime combines:
date
time
zone
Example:
ZonedDateTime meeting =
ZonedDateTime.of(
2026,
8,
8,
10,
0,
0,
0,
ZoneId.of(
"Europe/Tallinn"
)
);
This means:
2026-08-08
10:00
in Europe/Tallinn
Zoned Time Defines an Actual Moment
Because zone rules are known, Java can determine the corresponding:
Instant
Example:
Instant instant =
meeting.toInstant();
Convert an Instant to Local Zoned Time
Suppose system stores:
Instant timestamp
To display in Tallinn:
ZonedDateTime tallinnTime =
timestamp.atZone(
ZoneId.of(
"Europe/Tallinn"
)
);
To display in Dhaka:
ZonedDateTime dhakaTime =
timestamp.atZone(
ZoneId.of(
"Asia/Dhaka"
)
);
Same instant।
Different local representations।
This Is a Strong Backend Pattern
Store:
Instant
for actual events।
Display:
ZonedDateTime
using user's relevant time zone।
Conceptually:
Storage:
exact moment
Presentation:
local human time
Example
Suppose:
Instant createdAt =
Instant.now();
Then:
ZonedDateTime userTime =
createdAt.atZone(
ZoneId.of(
"Asia/Dhaka"
)
);
You have not changed when the event happened।
You changed only:
how the same moment is represented locally.
Converting LocalDateTime to Zoned Time
Suppose:
LocalDateTime local =
LocalDateTime.of(
2026,
8,
8,
10,
0
);
and we know it means Tallinn time:
ZonedDateTime zoned =
local.atZone(
ZoneId.of(
"Europe/Tallinn"
)
);
Now the previously ambiguous local time has a zone context।
Then Convert to Instant
Instant instant =
zoned.toInstant();
Flow:
LocalDateTime
+
ZoneId
↓
ZonedDateTime
↓
Instant
Do Not Invent a Zone After the Fact
If a stored LocalDateTime was created without knowing its true zone, later writing:
local.atZone(
ZoneId.of(
"UTC"
)
);
does not magically make it correct।
You are asserting:
This local time was intended as UTC.
That assertion must come from the original data contract।
Duration
Duration represents time-based amount।
Examples:
30 seconds
15 minutes
24 hours
Example:
Duration timeout =
Duration.ofSeconds(
30
);
Duration Between Instants
Duration elapsed =
Duration.between(
start,
end
);
Get seconds:
long seconds =
elapsed.toSeconds();
Example
Instant startedAt =
Instant.now();
// work
Instant finishedAt =
Instant.now();
Duration duration =
Duration.between(
startedAt,
finishedAt
);
This is appropriate for measuring elapsed timeline duration।
Duration Is Time-Based
Think:
seconds
minutes
hours
rather than human calendar months/years।
Period
Period represents date-based calendar amount।
Examples:
3 days
2 months
1 year
Example:
Period trialPeriod =
Period.ofDays(
30
);
Another:
Period membership =
Period.ofMonths(
6
);
Period Between Dates
Period age =
Period.between(
birthDate,
today
);
Then:
int years =
age.getYears();
Duration vs Period
Very important distinction:
Duration
→ timeline/time-based amount
Period
→ calendar/date-based amount
24 Hours Is Not Always the Same as One Calendar Day
This becomes important around Daylight Saving Time।
Suppose a local time zone changes its clock。
Then:
plus 1 calendar day
and:
plus exactly 24 hours
can lead to different local times।
Calendar Requirement
If requirement is:
Same local time tomorrow
calendar date arithmetic may be appropriate।
Example:
zonedDateTime.plusDays(
1
);
Exact Elapsed-Time Requirement
If requirement is:
Exactly 24 hours later
think in timeline terms:
instant.plus(
Duration.ofHours(
24
)
);
These business requirements are not always equivalent।
Period Example — Subscription Calendar Date
Suppose subscription renews:
one month later
Use:
LocalDate nextRenewal =
startDate.plus(
Period.ofMonths(
1
)
);
Not:
30 × 24 hours
because months have different lengths।
Duration Example — Timeout
Suppose request timeout:
30 seconds
Use:
Duration timeout =
Duration.ofSeconds(
30
);
A calendar Period makes no sense here।
DateTimeFormatter
Humans rarely want default ISO representation everywhere।
For formatting and parsing:
DateTimeFormatter
Formatting a Date
LocalDate date =
LocalDate.of(
2026,
8,
8
);
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern(
"dd/MM/yyyy"
);
String formatted =
date.format(
formatter
);
Result:
08/08/2026
Formatting Date and Time
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern(
"dd MMM yyyy HH:mm"
);
Then:
String value =
dateTime.format(
formatter
);
Pattern Case Matters
Date/time formatter pattern symbols are case-sensitive।
Examples:
MM
→ month
mm
→ minute
These are not the same।
A very common bug হলো month-এর জায়গায় minute pattern ব্যবহার করা।
Parsing
String:
08/08/2026
to LocalDate:
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern(
"dd/MM/yyyy"
);
LocalDate date =
LocalDate.parse(
"08/08/2026",
formatter
);
Prefer Standard Formats for Machine Interfaces
For APIs and persistence, standardized machine-readable formats are usually better than custom human presentation strings।
Example:
2026-08-08
for a date।
Or an unambiguous timestamp including zone/offset/UTC semantics।
Human formatting:
08 Aug 2026
belongs more naturally at presentation boundaries।
Parsing Invalid Input
This:
LocalDate.parse(
"not-a-date"
);
will fail।
User-provided date parsing is an input-validation boundary।
Do not assume all strings are valid।
Date Validation Through Types
Instead of storing:
String birthDate
throughout application code, parse once:
LocalDate birthDate
Now downstream code works with a proper date type।
This reduces invalid-state possibilities।
Use Types to Represent Meaning
Bad:
String createdAt;
String birthday;
String timeout;
All are strings but represent completely different concepts।
Better:
Instant createdAt;
LocalDate birthday;
Duration timeout;
Now type itself communicates semantics।
LocalDateTime.now() vs Instant.now()
A common question:
Which one should I use for createdAt?
For an event timestamp:
Instant.now()
is usually the stronger default।
Why?
Because:
createdAt
asks:
Exactly when did this happen?
not:
What did the local wall clock show?
Bad Timestamp Design
LocalDateTime createdAt =
LocalDateTime.now();
Then send it between services without zone information।
Now another system does not know which actual moment it represents।
Better
Instant createdAt =
Instant.now();
Convert to local user time only when necessary।
User-Scheduled Events Are Different
Suppose user schedules:
Live class at 10:00 Europe/Tallinn
on 2026-09-10
Here the business input includes:
local date
local time
zone
So model may involve:
ZonedDateTime
or:
LocalDateTime
+
ZoneId
depending on domain design।
Why Store Zone for Recurring Events?
Suppose requirement:
Every Monday at 09:00 Tallinn time
If you store only current UTC equivalent, Daylight Saving Time changes may shift local wall-clock behavior।
For recurring human schedules, the intended:
local time
+
zone rules
may matter more than one fixed UTC instant।
One-Time Event vs Recurring Schedule
A useful distinction:
One-time event
Occurs exactly once at a known moment
Store/represent exact:
Instant
plus zone for display if needed।
Recurring local schedule
Every day at 09:00 Europe/Tallinn
Needs local scheduling semantics and zone rules।
Daylight Saving Time Intuition
Some time zones change UTC offset during the year।
For example, a zone may use one offset in winter and another in summer।
Therefore:
Europe/Tallinn
is not equivalent to permanently hardcoding one offset।
Use ZoneId so Java's time-zone rules can resolve the correct offset for the date।
Do Not Hardcode User Time-Zone Offsets
Avoid business logic like:
utc.plusHours(
3
);
to mean:
Tallinn time
That may fail when the zone's applicable offset changes।
Use:
instant.atZone(
ZoneId.of(
"Europe/Tallinn"
)
);
Converting Between Zones
Suppose meeting:
ZonedDateTime tallinnMeeting
Convert the same instant to Dhaka:
ZonedDateTime dhakaMeeting =
tallinnMeeting.withZoneSameInstant(
ZoneId.of(
"Asia/Dhaka"
)
);
withZoneSameInstant()
Meaning:
Keep the same global moment,
show it in another time zone.
This is usually what you want for timezone conversion।
Do Not Confuse Same Instant with Same Local Time
These are different questions:
Same event in another zone?
versus:
Keep 10:00 but reinterpret it in another zone?
For normal user-facing conversion, preserve the instant।
Comparing Zoned Times
Two ZonedDateTime values may display different local times but refer to the same Instant।
When exact global ordering matters, converting/comparing timeline values is often clearer।
Example:
first.toInstant()
.isBefore(
second.toInstant()
);
Example — Course Publication Timestamp
record Course(
String code,
Instant publishedAt
) {
}
When Course is published:
Course course =
new Course(
"JAVA",
Instant.now()
);
For user display:
ZonedDateTime localPublishedAt =
course.publishedAt()
.atZone(
ZoneId.of(
"Asia/Dhaka"
)
);
Example — Course Start Date
Suppose Course starts on a calendar date and time-of-day is irrelevant:
record Course(
String code,
LocalDate startDate
) {
}
This is better than storing midnight Instant just to represent a date।
Do Not Invent Precision
If business concept is:
Birthday
do not model:
Instant birthday
because birthday usually has no meaningful exact global second।
Use:
LocalDate
Do Not Lose Precision Either
If business concept is:
Payment processed at exact moment
do not store only:
LocalDate paymentDate
because hour/minute/second information matters।
Choosing the Right Type
Ask:
Do I care only about date?
→ LocalDate
Only local clock time?
→ LocalTime
Date + clock time, no zone yet?
→ LocalDateTime
Exact global moment?
→ Instant
Human local moment with zone rules?
→ ZonedDateTime
Duration.between()
Suppose:
Instant startedAt;
Instant finishedAt;
Elapsed:
Duration elapsed =
Duration.between(
startedAt,
finishedAt
);
Check:
if (
elapsed.toSeconds()
> 5
) {
System.out.println(
"Slow operation"
);
}
Be Careful Measuring Program Performance
Instant.now() can be useful for business timestamps।
For precise benchmarking or elapsed execution measurement, specialized monotonic timing APIs may be more appropriate than wall-clock timestamps।
Do not turn business date/time APIs into a microbenchmarking strategy।
Period.between()
Suppose:
LocalDate start =
LocalDate.of(
2020,
1,
1
);
LocalDate end =
LocalDate.of(
2026,
8,
8
);
Then:
Period period =
Period.between(
start,
end
);
Can inspect:
period.getYears();
period.getMonths();
period.getDays();
Period Components Are Calendar Components
Period result:
6 years
7 months
7 days
style calendar decomposition হতে পারে।
Do not interpret getDays() alone as total number of days between distant dates।
It is the day component of the Period।
Need Total Number of Days?
For two LocalDate values, use a date-based unit operation rather than summing Period components manually।
Example:
long days =
ChronoUnit.DAYS.between(
startDate,
endDate
);
Import:
import java.time.temporal.ChronoUnit;
ChronoUnit
ChronoUnit useful for differences such as:
ChronoUnit.DAYS
ChronoUnit.HOURS
ChronoUnit.MINUTES
But choose units compatible with the temporal types and business semantics।
Comparing Dates Is Better Than Comparing Strings
Avoid:
if (
dateString.compareTo(
otherDateString
) > 0
) {
...
}
unless format semantics are intentionally designed for lexical ordering।
Better:
LocalDate date =
LocalDate.parse(
input
);
if (
date.isAfter(
otherDate
)
) {
...
}
Use date/time types for date/time logic।
DateTimeFormatter Should Be Reused
A formatter can be stored as a constant when reused։
Example:
private static final DateTimeFormatter DISPLAY_FORMAT =
DateTimeFormatter.ofPattern(
"dd MMM yyyy"
);
Then:
String formatted =
date.format(
DISPLAY_FORMAT
);
Avoid Repeated Magic Patterns
Instead of scattering:
DateTimeFormatter.ofPattern(
"dd/MM/yyyy"
)
everywhere, define formatting policy near presentation boundaries।
Storage Format vs Display Format
These are different concerns।
Storage/API:
stable
machine-readable
unambiguous
Display:
localized
human-friendly
Do not mix them unnecessarily।
Time Zone Should Be Explicit at Boundaries
If API accepts a scheduled local class time, define clearly whether input is:
UTC Instant
or:
LocalDateTime + ZoneId
Do not accept:
2026-09-10T10:00
and leave every service guessing which zone it means।
Example Request Model
Conceptually:
record ScheduleRequest(
LocalDateTime startsAt,
String zoneId
) {
}
Then:
ZoneId zone =
ZoneId.of(
request.zoneId()
);
ZonedDateTime scheduled =
request.startsAt()
.atZone(
zone
);
Better Value Type
Could also model:
record ScheduleRequest(
ZonedDateTime startsAt
) {
}
depending on serialization/API conventions।
The key principle:
time-zone semantics must not be ambiguous.
Common Mistake 1 — Using LocalDateTime for Every Timestamp
LocalDateTime does not identify a global moment।
For system event timestamps:
Instant
is often more appropriate।
Common Mistake 2 — Storing Dates as Strings
Example:
String createdAt;
This loses type safety and may introduce parsing ambiguity।
Prefer proper Java time types internally।
Common Mistake 3 — Hardcoding UTC Offsets
Avoid:
plusHours(
3
);
to represent a geographic zone।
Use:
ZoneId
Common Mistake 4 — Confusing MM and mm
Formatter:
MM
→ month
mm
→ minute
Case matters।
Common Mistake 5 — Forgetting Immutability
Wrong:
date.plusDays(
1
);
and expecting date to change।
Correct:
LocalDate tomorrow =
date.plusDays(
1
);
Common Mistake 6 — Using Duration for Calendar Months
Do not represent:
one month
as:
30 days
unless business definition explicitly says exactly 30 days।
For calendar month semantics:
Period.ofMonths(
1
)
or:
plusMonths(
1
)
is more appropriate।
Common Mistake 7 — Using Period for Exact Timeouts
A request timeout:
30 seconds
should use:
Duration
not Period।
Common Mistake 8 — Assuming Local Time Is an Instant
2026-08-08 10:00
without zone is not enough to identify exactly when something happened।
Common Mistake 9 — Converting Zones by Changing Hour Manually
Do not write timezone conversion as arithmetic:
time.plusHours(
difference
);
Use zone-aware conversion।
Common Mistake 10 — Mixing Presentation and Domain Logic
Do not make business decisions based on formatted strings।
Keep:
Instant
LocalDate
ZonedDateTime
for logic।
Format to String only near UI/API presentation boundaries when needed।
Common Mistake 11 — Default Time Zone Everywhere
Code such as:
LocalDate.now()
or:
ZonedDateTime.now()
uses a default zone context।
For business logic where zone matters, pass or define the intended zone explicitly।
Common Mistake 12 — Hiding Time-Zone Assumptions
If business says:
Subscription expires at midnight
ask:
Midnight in which zone?
Time-zone assumptions are part of the requirement।
Practical Example — Enrollment Expiry
Suppose an enrollment expires exactly:
72 hours
after activation।
Use Instant + Duration:
Instant activatedAt =
Instant.now();
Instant expiresAt =
activatedAt.plus(
Duration.ofHours(
72
)
);
Why Not LocalDateTime.plusDays(3)?
Because requirement is:
exactly 72 elapsed hours
not necessarily:
same local clock time three calendar dates later
Timeline semantics fit better।
Practical Example — Monthly Renewal
Suppose billing renewal date is:
one calendar month after 2026-01-31
Use:
LocalDate renewalDate =
LocalDate.of(
2026,
1,
31
).plusMonths(
1
);
Calendar API handles valid resulting date।
Practical Example — User Display
Store:
Instant createdAt;
Display in user's zone:
ZonedDateTime displayed =
createdAt.atZone(
userZone
);
Then format:
String output =
displayed.format(
DateTimeFormatter.ofPattern(
"dd MMM yyyy HH:mm"
)
);
Complete Example
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern(
"dd MMM yyyy HH:mm"
);
public static void main(String[] args) {
Instant publishedAt =
Instant.now();
Instant expiresAt =
publishedAt.plus(
Duration.ofHours(
48
)
);
ZoneId tallinn =
ZoneId.of(
"Europe/Tallinn"
);
ZoneId dhaka =
ZoneId.of(
"Asia/Dhaka"
);
ZonedDateTime tallinnPublished =
publishedAt.atZone(
tallinn
);
ZonedDateTime dhakaPublished =
publishedAt.atZone(
dhaka
);
System.out.println(
"Tallinn: "
+ tallinnPublished.format(
FORMATTER
)
);
System.out.println(
"Dhaka: "
+ dhakaPublished.format(
FORMATTER
)
);
System.out.println(
"Expires at: "
+ expiresAt
);
}
}
Same Instant:
publishedAt
different local representations:
Tallinn
Dhaka
Practice 1 — Birthday
Which type?
A person's birthday:
1995-04-12
Answer
LocalDate
Practice 2 — Daily Opening Time
Shop opens every day at 09:00.
Answer
LocalTime
Practice 3 — Database createdAt
Need exact time an entity was created।
Answer
Usually:
Instant
Practice 4 — Meeting
2026-10-10 at 15:00 Europe/Tallinn
Answer
ZonedDateTime
is a natural representation।
Practice 5 — Ambiguous Value
LocalDateTime.of(
2026,
10,
10,
15,
0
)
Does it identify an exact global moment?
Answer
No।
There is no zone or offset।
Practice 6 — Timeout
30 seconds
Answer
Duration
Practice 7 — Membership Length
6 calendar months
Answer
Period
or calendar plusMonths() arithmetic।
Practice 8 — Add One Day
Does:
date.plusDays(
1
);
mutate date?
Answer
No।
Java time types are immutable।
Practice 9 — Formatting
What is wrong with using:
dd/mm/yyyy
when mm is intended to mean month?
Answer
Lowercase:
mm
means minute।
Month is:
MM
Practice 10 — Time Zone
Why prefer:
ZoneId.of(
"Europe/Tallinn"
)
over manually adding hours?
Answer
Because ZoneId contains time-zone rules and can account for date-dependent offset changes such as Daylight Saving Time।
Practice 11 — Same Event in Another Zone
Given:
Instant eventTime
show it in Dhaka।
Solution
ZonedDateTime dhakaTime =
eventTime.atZone(
ZoneId.of(
"Asia/Dhaka"
)
);
Practice 12 — Parse Date
Input:
08/08/2026
Solution
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern(
"dd/MM/yyyy"
);
LocalDate date =
LocalDate.parse(
"08/08/2026",
formatter
);
Practice 13 — One Calendar Month
What should you avoid?
Assuming one month = 30 days
Answer
Use calendar-based operations:
plusMonths(
1
)
or:
Period.ofMonths(
1
)
when business requirement means a calendar month।
Practice 14 — 24-Hour Expiry
Token expires exactly 24 hours after creation।
Solution
Instant expiresAt =
createdAt.plus(
Duration.ofHours(
24
)
);
Practice 15 — Recurring Local Time
Requirement:
Every day at 09:00 Europe/Tallinn.
Would storing only one current UTC hour fully capture the rule?
Answer
No।
The rule is based on:
local time
+
time zone
and future zone offsets may vary।
True or False
LocalDatecontains a time zone.LocalTimecontains a date.LocalDateTimecontains date and time but no zone.Instantrepresents an exact global timeline point.ZoneIdcan represent geographic time-zone rules.ZonedDateTimecombines local date/time with a zone.- Java time objects such as
LocalDateare mutable. Durationis suitable for exact elapsed hours.Periodis suitable for calendar months.- One calendar day is always identical to exactly 24 elapsed hours in every time zone.
MMandmmmean the same thing in formatter patterns.Instantis usually a strong choice for backend event timestamps.LocalDateTimealone is enough to identify any event globally.- Geographic time-zone conversion should usually use
ZoneId. - Date/time values should always be stored as Strings internally.
Answers
1. False
2. False
3. True
4. True
5. True
6. True
7. False
8. True
9. True
10. False
11. False
12. True
13. False
14. True
15. False
Knowledge Check
Question 1
LocalDate কী represent করে?
Question 2
LocalDateTime এবং Instant-এর মূল difference কী?
Question 3
কেন LocalDateTime global timestamp হিসেবে ambiguous হতে পারে?
Question 4
ZoneId কেন fixed hour offset-এর চেয়ে richer?
Question 5
ZonedDateTime কী represent করে?
Question 6
Duration এবং Period-এর difference কী?
Question 7
কেন one month-কে blindly 30 days হিসেবে represent করা উচিত নয়?
Question 8
Java time types-এর immutability practical code-এ কীভাবে affect করে?
Question 9
DateTimeFormatter কেন প্রয়োজন?
Question 10
Backend createdAt field-এর জন্য Instant কেন useful?
Question 11
একই Instant কীভাবে Tallinn এবং Dhaka-তে different local clock time হিসেবে দেখা যেতে পারে?
Question 12
Recurring local schedule-এর জন্য time zone কেন preserve করা গুরুত্বপূর্ণ?
Knowledge Check Answers
Answer 1
LocalDate শুধু calendar date represent করে:
year
month
day
এতে time বা time zone নেই।
Answer 2
LocalDateTime একটি local wall-clock date এবং time represent করে কিন্তু time zone জানে না।
Instant global timeline-এর একটি exact moment represent করে।
Answer 3
কারণ:
2026-08-08 10:00
Tallinn, Dhaka, London বা অন্য যেকোনো zone-এর local time হতে পারে।
Zone ছাড়া কোন actual global moment বোঝানো হয়েছে তা জানা যায় না।
Answer 4
ZoneId একটি region-এর historical/current time-zone rules represent করে।
Fixed offset:
+03:00
শুধু একটি offset value।
ZoneId date অনুযায়ী applicable offset determine করতে পারে।
Answer 5
এটি:
local date
+
local time
+
time zone
একসঙ্গে represent করে।
Answer 6
Duration time-based elapsed amount represent করে:
seconds
minutes
hours
Period calendar-based amount represent করে:
days
months
years
Answer 7
কারণ calendar months-এর length একই নয়।
এক মাস হতে পারে:
28
29
30
31 days
Business requirement যদি calendar month হয়, calendar arithmetic ব্যবহার করতে হবে।
Answer 8
Operations original object modify করে না।
Example:
date.plusDays(
1
);
new LocalDate return করে।
Result ব্যবহার করতে variable assign করতে হবে।
Answer 9
Human-readable String এবং Java date/time type-এর মধ্যে formatting/parsing করতে।
Example:
LocalDate
↔
08/08/2026
Answer 10
কারণ createdAt সাধারণত প্রশ্নের উত্তর দেয়:
Exactly when was this created?
Instant time-zone ambiguity ছাড়াই exact global moment represent করে।
Answer 11
Instant same global moment ধরে রাখে।
Different ZoneId apply করলে সেই moment-এর local wall-clock representation zone অনুযায়ী পরিবর্তিত হয়।
Answer 12
কারণ recurring schedule-এর business rule প্রায়ই:
09:00 local time
কে preserve করতে চায়।
Time-zone offset future dates-এ change হলেও ZoneId local scheduling rule correctly interpret করতে সাহায্য করে।
Practical Type Selection Guide
Date only:
LocalDate
Time only:
LocalTime
Date + time, zone not yet known:
LocalDateTime
Exact global moment:
Instant
Local date/time with time-zone rules:
ZonedDateTime
Exact elapsed time:
Duration
Calendar amount:
Period
Human formatting/parsing:
DateTimeFormatter
Backend Date/Time Strategy
একটি useful starting strategy:
System event timestamp
→ Instant
User birthday / due date
→ LocalDate
Daily local clock time
→ LocalTime
User-scheduled zoned event
→ ZonedDateTime
or LocalDateTime + ZoneId
Exact timeout / expiry duration
→ Duration
Calendar subscription period
→ Period
Core Mental Model
Date/time type choose করার আগে প্রশ্ন করুন:
এই value আসলে কী বোঝাচ্ছে?
If:
কোন দিন?
→ LocalDate
If:
দিনের কোন সময়?
→ LocalTime
If:
local date and time কী?
→ LocalDateTime
If:
exactly কখন ঘটেছে?
→ Instant
If:
কোন local date/time এবং কোন zone?
→ ZonedDateTime
এই distinctionগুলো type system-এর মধ্যে রাখলে অনেক subtle bug design stage-এই avoid করা যায়।
Lesson Summary
এই lesson-এ আমরা Modern Java Date and Time API-এর foundation শিখেছি।
আমরা শিখেছি:
java.timemodern date/time types provide করেLocalDatedate-only valueLocalTimetime-only valueLocalDateTimedate + time কিন্তু zone ছাড়াLocalDateTimeglobal timestamp নয়Instantexact global moment represent করেZoneIdgeographic time-zone rules represent করেZonedDateTimelocal date/time এবং zone combine করে- একই
Instantdifferent zones-এ different local times হিসেবে display হতে পারে Durationexact time-based amount-এর জন্যPeriodcalendar-based amount-এর জন্য- 24 hours এবং one calendar day সবসময় semantically same নয়
- One month-কে blindly 30 days ধরা উচিত নয়
- Java time types immutable
- Date/time arithmetic new object return করে
DateTimeFormatterparsing এবং formatting handle করে- Formatter pattern case-sensitive
- System timestamps-এর জন্য
Instantstrong default হতে পারে - User-facing local times-এর জন্য appropriate
ZoneIdapply করতে হয় - Geographic zones manually hour addition দিয়ে model করা উচিত নয়
- Recurring local schedules-এর জন্য zone semantics preserve করা important
- Proper date/time types String-based date handling-এর চেয়ে safer
- Storage semantics এবং display formatting আলাদা concern
সবচেয়ে গুরুত্বপূর্ণ principle:
Time নিয়ে কাজ করার আগে
type choose করবেন না।
আগে decide করুন
time value-এর meaning কী।
কারণ:
2026-08-08 10:00
একটি date/time value হতে পারে।
কিন্তু:
2026-08-08 10:00 Europe/Tallinn
এবং:
an exact Instant
একই concept নয়।
Next Lesson
পরবর্তী lesson:
Modern Java Language Features
আমরা শিখব:
var- Local variable type inference
- কখন
varuseful - কখন explicit type clearer
- Switch expressions
yield- Arrow-style switch cases
- Text blocks
- Pattern matching with
instanceof - Pattern matching with
switch - Sealed classes overview যেখানে appropriate
- Modern syntax ব্যবহার করে code concise করা
- Modern syntax overuse না করা
- Readability এবং type clarity preserve করা