A complete, dependency-free Persian (Solar Hijri / Jalali) calendar for Go —
shaped like the standard time package.
go get github.com/amiranmanesh/go-persian-calendar
Everything the standard time package gives you, in the Persian calendar.
Now, Date, Add, AddDate, Sub, Before, After, Compare, Truncate, Round — same names, same semantics.
Pattern letters (yyyy/MM/dd) and the Go reference time (2006/01/02). Pick whichever your team already reads.
Parse, ParseInLocation and their reference-time twins, with a ParseError that names the element that failed.
Implements json.Marshaler, encoding.TextMarshaler, driver.Valuer and sql.Scanner. No wrapper type needed.
Dari month names are selected automatically in Asia/Kabul, or explicitly with the MMI pattern.
Every conversion goes through the Julian Day Number, so it stays correct on both sides of the 1582 Gregorian reform.
An optional holiday package answers whether a date is a day off — and says so when a lunar date is still an estimate.
Iran fixes lunar holidays by moon sighting. No algorithm can predict that, so the package does not pretend otherwise.
import "github.com/amiranmanesh/go-persian-calendar/holiday"
cal := holiday.Iran()
cal.IsHoliday(pt) // is this a day off, Fridays included?
cal.Lookup(pt).Title() // روز طبیعت، سیزده بهدر
cal.NextWorkday(pt) // the next working day
cal.Workdays(from, to) // working days in a range
Nowruz, 22 Bahman, 13 Farvardin. Fixed by law, expressed as rules in code, correct forever. Reported as Confirmed.
Eid al-Fitr, Ashura, Arbaeen. The arithmetic calendar disagrees with the announced date 43% of the time, so an unsettled year is reported as Estimated.
An air pollution closure or an election cannot be predicted at all. A monthly workflow reconciles them and opens a pull request for review.
The data is embedded at build time, so the package does no I/O. The same file is served at
/data/v1/iran.json for runtime reloads and non-Go consumers.
A few lines each, straight from the test suite.
import ptime "github.com/amiranmanesh/go-persian-calendar"
// Gregorian to Persian
gt := time.Date(2016, time.January, 1, 12, 1, 1, 0, ptime.Iran())
pt := ptime.New(gt)
fmt.Println(pt.Date()) // 1394 دی 11
// Persian to Gregorian
pt = ptime.Date(1394, ptime.Mehr, 2, 12, 59, 59, 0, ptime.Iran())
fmt.Println(pt.Time().Format(time.DateOnly)) // 2015-09-24pt := ptime.Unix(1454277270, 0)
pt.Format("yyyy/MM/dd E hh:mm:ss a") // 1394/11/11 یکشنبه 09:54:30 ب.ظ
pt.Format(ptime.RFC3339) // 1394-11-11T21:54:30+03:30
pt.Format(ptime.LongDate) // یکشنبه 11 بهمن 1394
pt.TimeFormat("2 Jan 2006") // 11 بهمن 1394
// Write into an existing buffer, no string allocation
buf = pt.AppendFormat(buf[:0], ptime.DateTime)pt, err := ptime.Parse(ptime.DateTime, "1394-07-02 12:59:59")
if err != nil {
var perr *ptime.ParseError
errors.As(err, &perr) // names the layout element that failed
}
// Month names, either script
pt, err = ptime.ParseInLocation("d MMM yyyy", "2 مهر 1394", ptime.Iran())
// Reference-time layouts work too
pt, err = ptime.ParseTimeFormat("2006/01/02", "1394/07/02")type Event struct {
Name string `json:"name"`
At ptime.Time `json:"at"`
}
json.Marshal(Event{
Name: "نوروز",
At: ptime.Date(1404, ptime.Farvardin, 1, 0, 0, 0, 0, ptime.Iran()),
})
// {"name":"نوروز","at":"1404-01-01T00:00:00+03:30"}
// The zero Time round trips as null, and as SQL NULL through Value/Scan.pt := ptime.Now()
pt.IsLeap() // is this a leap year?
pt.YearDay() // day of year
pt.RMonthDay() // days left in the month
pt.MonthWeek() // week of month
pt.BeginningOfWeek() // Shanbeh at 00:00:00
pt.LastMonthDay() // 29, 30 or 31, whichever is right
pt.Tomorrow().Weekday() // شنبهConstants for the shapes you reach for most.
| Constant | Layout | Example |
|---|---|---|
RFC3339 | yyyy-MM-ddTHH:mm:ssZ | 1394-07-02T12:59:59+03:30 |
RFC3339Nano | yyyy-MM-ddTHH:mm:ss.999999999Z | 1394-07-02T12:59:59.052+03:30 |
DateTime | yyyy-MM-dd HH:mm:ss | 1394-07-02 12:59:59 |
DateOnly | yyyy-MM-dd | 1394-07-02 |
TimeOnly | HH:mm:ss | 12:59:59 |
Kitchen | h:mm a | 12:59 ب.ظ |
LongDate | E d MMM yyyy | پنجشنبه 2 مهر 1394 |
The full pattern-letter table lives in the API reference.
پکیج ptime تبدیل بین تقویم هجری شمسی و میلادی را انجام میدهد و نوع Time را
در اختیار شما میگذارد که مانند time.Time رفتار میکند: همان نام متدها، همان معنای مقداری
و همان روش قالببندی. قالببندی، تجزیه، JSON و SQL همگی پشتیبانی میشوند و نام ماهها هم به شکل
ایرانی و هم دری در دسترس است.