File

apps/recallassess/recallassess-api/src/api/shared/timezone/company-timezone.service.ts

Description

Nest injectable wrapper (Company has no separate company_timezone column).

Index

Methods

Methods

resolve
resolve(company: CompanyTimezoneInput | null | undefined)
Parameters :
Name Type Optional
company CompanyTimezoneInput | null | undefined No
Returns : string
import { Injectable } from "@nestjs/common";

/**
 * Maps ISO 3166-1 alpha-2 country codes to a primary IANA timezone.
 * Used to derive company timezone from Company.country when preferred_timezone is not set.
 * Source: IANA tzdb / common conventions (one primary zone per country where applicable).
 *
 * Keep in sync with libs/recallassess/shared-ng/src/lib/utils/company-timezone.utils.ts
 */
const COUNTRY_TO_TIMEZONE: Record<string, string> = {
  AE: "Asia/Dubai",
  AU: "Australia/Sydney",
  IN: "Asia/Kolkata",
  US: "America/New_York",
  GB: "Europe/London",
  UK: "Europe/London",
  DE: "Europe/Berlin",
  FR: "Europe/Paris",
  CA: "America/Toronto",
  BR: "America/Sao_Paulo",
  JP: "Asia/Tokyo",
  CN: "Asia/Shanghai",
  SG: "Asia/Singapore",
  HK: "Asia/Hong_Kong",
  MY: "Asia/Kuala_Lumpur",
  SA: "Asia/Riyadh",
  EG: "Africa/Cairo",
  ZA: "Africa/Johannesburg",
  NG: "Africa/Lagos",
  KE: "Africa/Nairobi",
  RU: "Europe/Moscow",
  NL: "Europe/Amsterdam",
  ES: "Europe/Madrid",
  IT: "Europe/Rome",
  CH: "Europe/Zurich",
  SE: "Europe/Stockholm",
  PL: "Europe/Warsaw",
  TR: "Europe/Istanbul",
  PK: "Asia/Karachi",
  BD: "Asia/Dhaka",
  ID: "Asia/Jakarta",
  TH: "Asia/Bangkok",
  VN: "Asia/Ho_Chi_Minh",
  PH: "Asia/Manila",
  KR: "Asia/Seoul",
  NZ: "Pacific/Auckland",
  MX: "America/Mexico_City",
  AR: "America/Argentina/Buenos_Aires",
  CL: "America/Santiago",
  CO: "America/Bogota",
  PT: "Europe/Lisbon",
  IE: "Europe/Dublin",
  BE: "Europe/Brussels",
  AT: "Europe/Vienna",
  NO: "Europe/Oslo",
  DK: "Europe/Copenhagen",
  FI: "Europe/Helsinki",
  GR: "Europe/Athens",
  IL: "Asia/Jerusalem",
  QA: "Asia/Qatar",
  KW: "Asia/Kuwait",
  BH: "Asia/Bahrain",
  OM: "Asia/Muscat",
  JO: "Asia/Amman",
  LB: "Asia/Beirut",
  SY: "Asia/Damascus",
  IQ: "Asia/Baghdad",
  IR: "Asia/Tehran",
};

const DEFAULT_TIMEZONE = "UTC";

/**
 * Returns the primary IANA timezone for a country code.
 * @param countryCode ISO 3166-1 alpha-2 (e.g. "AE", "US"). Case-insensitive.
 * @returns IANA timezone string (e.g. "Asia/Dubai") or "UTC" if unknown/missing.
 */
export function getTimezoneForCountry(countryCode: string | null | undefined): string {
  if (!countryCode || typeof countryCode !== "string") {
    return DEFAULT_TIMEZONE;
  }
  const normalized = countryCode.trim().toUpperCase();
  if (!normalized) return DEFAULT_TIMEZONE;
  return COUNTRY_TO_TIMEZONE[normalized] ?? DEFAULT_TIMEZONE;
}

/** Company columns used to resolve the effective IANA zone (no separate DB `company_timezone`). */
export interface CompanyTimezoneInput {
  country?: string | null;
  preferred_timezone?: string | null;
}

/**
 * Resolves the effective IANA timezone for a company:
 * - If preferred_timezone is set, use it.
 * - Otherwise derive from country code.
 * - Fallback to UTC.
 */
export function resolveCompanyTimezone(company: CompanyTimezoneInput | null | undefined): string {
  if (!company) return DEFAULT_TIMEZONE;
  if (company.preferred_timezone && company.preferred_timezone.trim()) {
    return company.preferred_timezone.trim();
  }
  return getTimezoneForCountry(company.country);
}

/** Nest injectable wrapper (Company has no separate `company_timezone` column). */
@Injectable()
export class CompanyTimezoneService {
  resolve(company: CompanyTimezoneInput | null | undefined): string {
    return resolveCompanyTimezone(company);
  }
}

results matching ""

    No results matching ""