Problem: the hexagonal refactor churns the backend tree for nine more phases; the UI delivery stack (web/ SPA, cmd/desktop Wails wrapper, compose/web image) must move to its own repo first so doc/layout rewrites land once on a backend-only tree. Change: - New repo git.hubris.network/dtoro/oikos-web (v0.33.0): web/, desktop/ (updateURL repointed to oikos-web releases), compose/, own CI (web + desktop jobs), own deploy script (CI-green gate, TOCTOU guard, version-tagged images, prune-to-3), own webhook receiver on :9798 + launchd unit, own compose project publishing the same 8091:80. - Cutover executed on mac-mini in order: oikos stack's web service stopped+removed, oikos-web project brought up on 8091; outer Caddy untouched (targets the published port) — serving + Authentik flow + /wails 404 quirk verified post-cutover. - Stripped from oikos: web/, cmd/desktop/, compose/web/, desktop CI workflow, ci.yml web job, Makefile ui/desktop/desktop-package/install targets, the compose web service, oikos-web from deploy.sh's fallback prune list; wails + go-keyring dropped from go.mod, vendor synced. - README / CONTRIBUTING / AGENTS.md / .agents dev+operations docs now point at the new repo; mbse + mascot design docs carry a path note. Risk: production SPA serving depends on the new pipeline now; rollback is versioned-image re-up of the old web service from a pre-split checkout (port 8091). Desktop builds installed before the split still check dtoro/oikos releases — one manual reinstall, noted in the oikos-web release notes. Verification: go vet, make test (race), make generate-check, golangci (no new findings; baseline down 400→365); post-cutover curls — localhost:8091 200, /wails/runtime.js 404, outer Caddy 302 Authentik.
135 lines
3.8 KiB
TypeScript
135 lines
3.8 KiB
TypeScript
/*
|
|
* Copyright 2020 Adobe. All rights reserved.
|
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
* governing permissions and limitations under the License.
|
|
*/
|
|
|
|
// Portions of the code in this file are based on code from ICU.
|
|
// Original licensing can be found in the NOTICE file in the root directory of this source tree.
|
|
|
|
import {AnyCalendarDate, CalendarIdentifier} from '../types';
|
|
import {CalendarDate} from '../CalendarDate';
|
|
import {
|
|
fromExtendedYear,
|
|
GregorianCalendar,
|
|
gregorianToJulianDay,
|
|
isLeapYear
|
|
} from './GregorianCalendar';
|
|
|
|
// Starts in 78 AD,
|
|
const INDIAN_ERA_START = 78;
|
|
|
|
// The Indian year starts 80 days later than the Gregorian year.
|
|
const INDIAN_YEAR_START = 80;
|
|
|
|
/**
|
|
* The Indian National Calendar is similar to the Gregorian calendar, but with
|
|
* years numbered since the Saka era in 78 AD (Gregorian). There are 12 months
|
|
* in each year, with either 30 or 31 days. Only one era identifier is supported: 'saka'.
|
|
*/
|
|
export class IndianCalendar extends GregorianCalendar {
|
|
identifier: CalendarIdentifier = 'indian';
|
|
|
|
fromJulianDay(jd: number): CalendarDate {
|
|
// Gregorian date for Julian day
|
|
let date = super.fromJulianDay(jd);
|
|
|
|
// Year in Saka era
|
|
let indianYear = date.year - INDIAN_ERA_START;
|
|
|
|
// Day number in Gregorian year (starting from 0)
|
|
let yDay = jd - gregorianToJulianDay(date.era, date.year, 1, 1);
|
|
|
|
let leapMonth: number;
|
|
if (yDay < INDIAN_YEAR_START) {
|
|
// Day is at the end of the preceding Saka year
|
|
indianYear--;
|
|
|
|
// Days in leapMonth this year, previous Gregorian year
|
|
leapMonth = isLeapYear(date.year - 1) ? 31 : 30;
|
|
yDay += leapMonth + 31 * 5 + 30 * 3 + 10;
|
|
} else {
|
|
// Days in leapMonth this year
|
|
leapMonth = isLeapYear(date.year) ? 31 : 30;
|
|
yDay -= INDIAN_YEAR_START;
|
|
}
|
|
|
|
let indianMonth: number;
|
|
let indianDay: number;
|
|
if (yDay < leapMonth) {
|
|
indianMonth = 1;
|
|
indianDay = yDay + 1;
|
|
} else {
|
|
let mDay = yDay - leapMonth;
|
|
if (mDay < 31 * 5) {
|
|
indianMonth = Math.floor(mDay / 31) + 2;
|
|
indianDay = (mDay % 31) + 1;
|
|
} else {
|
|
mDay -= 31 * 5;
|
|
indianMonth = Math.floor(mDay / 30) + 7;
|
|
indianDay = (mDay % 30) + 1;
|
|
}
|
|
}
|
|
|
|
return new CalendarDate(this, indianYear, indianMonth, indianDay);
|
|
}
|
|
|
|
toJulianDay(date: AnyCalendarDate): number {
|
|
let extendedYear = date.year + INDIAN_ERA_START;
|
|
let [era, year] = fromExtendedYear(extendedYear);
|
|
|
|
let leapMonth: number;
|
|
let jd: number;
|
|
if (isLeapYear(year)) {
|
|
leapMonth = 31;
|
|
jd = gregorianToJulianDay(era, year, 3, 21);
|
|
} else {
|
|
leapMonth = 30;
|
|
jd = gregorianToJulianDay(era, year, 3, 22);
|
|
}
|
|
|
|
if (date.month === 1) {
|
|
return jd + date.day - 1;
|
|
}
|
|
|
|
jd += leapMonth + Math.min(date.month - 2, 5) * 31;
|
|
|
|
if (date.month >= 8) {
|
|
jd += (date.month - 7) * 30;
|
|
}
|
|
|
|
jd += date.day - 1;
|
|
return jd;
|
|
}
|
|
|
|
getDaysInMonth(date: AnyCalendarDate): number {
|
|
if (date.month === 1 && isLeapYear(date.year + INDIAN_ERA_START)) {
|
|
return 31;
|
|
}
|
|
|
|
if (date.month >= 2 && date.month <= 6) {
|
|
return 31;
|
|
}
|
|
|
|
return 30;
|
|
}
|
|
|
|
getYearsInEra(): number {
|
|
// 9999-12-31 gregorian is 9920-10-10 indian.
|
|
// Round down to 9919 for the last full year.
|
|
return 9919;
|
|
}
|
|
|
|
getEras(): string[] {
|
|
return ['saka'];
|
|
}
|
|
|
|
balanceDate(): void {}
|
|
}
|