PhSoft Docs

PL/SQL function that converts Gregorian dates to Hijri

FUNCTION Georgian2Hijri(G_DATE Date) RETURN Varchar2 IS H_DAY NUMBER(2):=0; HDAY VARCHAR2(2); H_MONTH NUMBER(2):=1; HMONTH VARCHAR2(2); H_YEAR NUMBER(4):=1; FGDATE DATE; I_LOOP NUMBER; HY NUMBER; MONTH_NAME VARCHAR2(40); BEGIN FGDATE := TO_DATE('14-07-0622','DD-MM-YYYY'); I_LOOP := G_DATE - FGDATE; LOOP IF I_LOOP<355 THEN EXIT; END IF; HY := TRUNC( H_YEAR / 30 ) * 30; IF (H_YEAR - HY) IN (2,5,7,10,13,16,18,21,24,26,29) THEN H_YEAR := H_YEAR + 1; I_LOOP := I_LOOP - 355; ELSE I_LOOP := I_LOOP - 354; H_YEAR := H_YEAR + 1; END IF; END LOOP; FOR I IN 1..I_LOOP LOOP H_DAY := H_DAY + 1; IF (H_MONTH=1 OR H_MONTH=3 OR H_MONTH=5 OR H_MONTH=7 OR H_MONTH=9 OR H_MONTH=11) AND H_DAY>30 THEN H_MONTH := H_MONTH + 1; H_DAY := 1; END IF; IF (H_MONTH=2 OR H_MONTH=4 OR H_MONTH=6 OR H_MONTH=8 OR H_MONTH=10)AND H_DAY>29 THEN H_MONTH := H_MONTH + 1; H_DAY := 1; END IF; HY := TRUNC( H_YEAR / 30 ) * 30; IF (H_YEAR - HY) IN (2,5,7,10,13,16,18,21,24,26,29) THEN IF H_MONTH=12 AND H_DAY>30 THEN H_MONTH := H_MONTH + 1; H_DAY := 1; IF H_MONTH>12 THEN H_YEAR := H_YEAR + 1; H_MONTH := 1; END IF; END IF; ELSE IF H_MONTH=12 AND H_DAY>29 THEN H_MONTH := H_MONTH + 1; H_DAY := 1; IF H_MONTH>12 THEN H_YEAR := H_YEAR + 1; H_MONTH := 1; END IF; END IF; END IF; END LOOP; SELECT DECODE(H_MONTH ,1,'محرم' ,2,'صفر' ,3,'ربيع الأول' ,4,'ربيع الثاني ,5,'جمادى الأولى ,6,'جمادة الآخرة ,7,'رجب' ,8,'شعبان' ,9,'رمضان' ,10,'شوال' ,11,'ذي القعدة' ,12,ذي الحجة',NULL) INTO MONTH_NAME FROM DUAL; IF H_DAY<10 THEN HDAY := '0' || TO_CHAR(H_DAY); ELSE HDAY := TO_CHAR(H_DAY); END IF; IF H_MONTH<10 THEN HMONTH := '0' || TO_CHAR(H_MONTH); ELSE HMONTH := TO_CHAR(H_MONTH); END IF; Return (HDAY || '-' || MONTH_NAME || '-' || TO_CHAR(H_YEAR)); END Georgian2Hijri;
 0
FUNCTION Georgian2Hijri(G_DATE Date) RETURN Varchar2 IS
 1
  H_DAY      NUMBER(2):=0;
 2
  HDAY       VARCHAR2(2);
 3
  H_MONTH    NUMBER(2):=1;
 4
  HMONTH     VARCHAR2(2);
 5
  H_YEAR     NUMBER(4):=1;
 6
  FGDATE     DATE;
 7
  I_LOOP     NUMBER;
 8
  HY         NUMBER;
 9
  MONTH_NAME VARCHAR2(40);
 10
BEGIN
 11
  FGDATE := TO_DATE('14-07-0622','DD-MM-YYYY');
 12
  I_LOOP := G_DATE - FGDATE;
 13
  LOOP
 14
    IF I_LOOP<355 THEN
 15
      EXIT;
 16
    END IF;
 17
    HY := TRUNC( H_YEAR / 30 ) * 30;
 18
    IF (H_YEAR - HY) IN (2,5,7,10,13,16,18,21,24,26,29) THEN
 19
      H_YEAR := H_YEAR + 1;
 20
      I_LOOP := I_LOOP - 355;
 21
    ELSE
 22
      I_LOOP := I_LOOP - 354;
 23
      H_YEAR := H_YEAR + 1;
 24
    END IF;
 25
  END LOOP; 
 26
  FOR I IN 1..I_LOOP LOOP
 27
    H_DAY := H_DAY + 1;
 28
    IF (H_MONTH=1 OR H_MONTH=3 OR H_MONTH=5 OR H_MONTH=7 OR H_MONTH=9 OR H_MONTH=11) AND H_DAY>30 THEN
 29
      H_MONTH := H_MONTH + 1;
 30
      H_DAY   := 1;
 31
    END IF;
 32
    IF (H_MONTH=2 OR H_MONTH=4 OR H_MONTH=6 OR H_MONTH=8 OR H_MONTH=10)AND H_DAY>29 THEN
 33
      H_MONTH := H_MONTH + 1;
 34
      H_DAY   := 1;
 35
    END IF;
 36
    HY := TRUNC( H_YEAR / 30 ) * 30;
 37
    IF (H_YEAR - HY) IN (2,5,7,10,13,16,18,21,24,26,29) THEN
 38
      IF H_MONTH=12 AND H_DAY>30 THEN
 39
        H_MONTH := H_MONTH + 1;
 40
        H_DAY   := 1;
 41
        IF H_MONTH>12 THEN
 42
          H_YEAR  := H_YEAR + 1;
 43
          H_MONTH := 1;
 44
        END IF;
 45
      END IF;
 46
    ELSE
 47
      IF H_MONTH=12 AND H_DAY>29 THEN
 48
        H_MONTH := H_MONTH + 1;
 49
        H_DAY   := 1;
 50
        IF H_MONTH>12 THEN
 51
          H_YEAR  := H_YEAR + 1;
 52
          H_MONTH := 1;
 53
        END IF;
 54
      END IF;
 55
    END IF;
 56
  END LOOP;
 57
  SELECT DECODE(H_MONTH
 58
         ,1,'محرم'
 59
         ,2,'صفر'
 60
         ,3,'ربيع الأول'
 61
         ,4,'ربيع الثاني
 62
         ,5,'جمادى الأولى
 63
         ,6,'جمادة الآخرة
 64
         ,7,'رجب'
 65
         ,8,'شعبان'
 66
         ,9,'رمضان'
 67
         ,10,'شوال'
 68
         ,11,'ذي القعدة'
 69
         ,12,ذي الحجة',NULL)
 70
    INTO MONTH_NAME
 71
    FROM DUAL;
 72
  IF H_DAY<10 THEN
 73
    HDAY := '0' || TO_CHAR(H_DAY);
 74
  ELSE
 75
    HDAY := TO_CHAR(H_DAY);
 76
  END IF;
 77
  IF H_MONTH<10 THEN
 78
    HMONTH := '0' || TO_CHAR(H_MONTH);
 79
  ELSE
 80
    HMONTH := TO_CHAR(H_MONTH);
 81
  END IF;
 82
  Return (HDAY || '-' || MONTH_NAME || '-' || TO_CHAR(H_YEAR));
 83
END Georgian2Hijri;
Key Components
1. Input/Output
- Takes Gregorian date (`G_DATE`)
- Returns Hijri date as string (e.g., 01-ربيع الأول-1446)

2. Base Reference
Uses the Hijri epoch: 14 July 622 AD (`FGDATE`)

3. Variables
- `H_DAY/H_MONTH/H_YEAR`: Track Hijri date components
- `I_LOOP`: Days between input date and epoch
- `HY`: Leap year calculation helper

Conversion Process
1. Year Calculation
- Subtracts epoch date from input date to get total days (`I_LOOP`)
- Uses 30-year lunar cycles (11 leap years per cycle):
- Regular years = 354 days
- Leap years = 355 days
- Adjusts year count based on remaining days

2. Day/Month Calculation
- Processes remaining days using Hijri month rules:
- Odd months = 30 days (Muharram, Safar, etc.)
- Even months = 29 days
- Dhu al-Hijjah (12th month) varies:
- 30 days in leap years
- 29 days otherwise

3. Month Names
Uses Arabic month names via `DECODE`:

1 → محرم (Muharram)
3 → ريع الأول (Rabi' al-Awwal)
9 → رمضان (Ramadan)
12 → ذو الحجة (Dhu al-Hijjah)


4. Formatting
- Adds leading zeros to single-digit days/months
- Returns final string in DD-MonthName-YYYY format

Key Characteristics
- Algorithm Type: Approximate astronomical calculation
- Accuracy: Follows tabular Islamic calendar rules
- Limitations:
- Doesn't account for lunar sightings
- Uses fixed leap year pattern
- Month names require Unicode support

This implementation provides a practical conversion method for applications needing approximate Hijri dates without real-time moon observations.