<?php
namespace nur\m;

use nur\date;

/**
 * Class sql_date: méthodes pour gérer des dates SQL au format YYYY-mm-dd
 */
class sql_date {
  /**
   * Tester si $date est une date/heure valide de la forme "YYYY-mm-dd HH:MM:SS"
   *
   * Si oui, $ms obtient les 6 éléments de la chaine
   */
  static function is_datetime($date, ?array &$ms=null): bool {
    return is_string($date) && preg_match('/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/', $date, $ms);
  }

  /**
   * Tester si $date est une date valide de la forme "YYYY-mm-dd [00:00:00]"
   *
   * Si oui, $ms obtient les 3 éléments de la chaine
   */
  static function is_date($date, ?array &$ms=null): bool {
    return is_string($date) && preg_match('/^(\d{4})-(\d{2})-(\d{2})(?: 00:00:00)?$/', $date, $ms);
  }

  /** retourner la date/heure courante au format 'YYYY-mm-dd HH:MM:SS' */
  static function datetime(): string {
    return strftime("%Y-%m-%d %H:%M:%S");
  }

  /** retourner la date courante au format 'YYYY-mm-dd' */
  static function date(): string {
    return strftime("%Y-%m-%d");
  }

  /**
   * transformer une date/heure française "dd/mm/YYYY [HH:MM:SS]" au format
   * SQL "YYYY-mm-dd HH:MM:SS" pour insertion ou mise à jour de la base de
   * données
   */
  static function _from_datetime(string $date): string {
    $ms = null;
    if (date::is_datetime($date, $ms)) {
      $d = intval($ms[1]);
      $m = intval($ms[2]);
      $y = date::fix_any_year($ms[3]);
      $H = intval($ms[4]);
      $M = intval($ms[5]);
      $S = intval(isset($ms[6])? $ms[6]: 0);
    } elseif (date::is_date($date, $ms)) {
      $d = intval($ms[1]);
      $m = intval($ms[2]);
      $y = date::fix_any_year($ms[3]);
      $H = 0;
      $M = 0;
      $S = 0;
    } else {
      return $date;
    }
    return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $y, $m, $d, $H, $M, $S);
  }

  /**
   * transformer une date/heure française "dd/mm/YYYY [HH:MM:SS]" au format
   * SQL "YYYY-mm-dd HH:MM:SS" pour insertion ou mise à jour de la base de
   * données.
   * Retourner inchangées les valeurs null et false ainsi que les dates invalides
   */
  static function from_datetime($date) {
    if ($date === null || $date === false) return $date;
    else return self::_from_datetime($date);
  }

  /**
   * transformer une date française "dd/mm/YYYY" au format sql "YYYY-mm-dd"
   * pour insertion ou mise à jour de la base de données
   */
  static function _from_date(string $date): string {
    $ms = null;
    if (date::is_datetime($date, $ms)) {
      $d = intval($ms[1]);
      $m = intval($ms[2]);
      $y = date::fix_any_year($ms[3]);
    } elseif (date::is_date($date, $ms)) {
      $d = intval($ms[1]);
      $m = intval($ms[2]);
      $y = date::fix_any_year($ms[3]);
    } else {
      return $date;
    }
    return sprintf("%04d-%02d-%02d", $y, $m, $d);
  }

  /**
   * transformer une date française "dd/mm/YYYY" au format sql "YYYY-mm-dd"
   * pour insertion ou mise à jour de la base de données
   * Retourner inchangées les valeurs null et false ainsi que les dates invalides
   */
  static function from_date(?string $date): ?string {
    if ($date === null || $date === false) return $date;
    else return self::_from_date($date);
  }

  /**
   * transformer une date sql "YYYY-mm-dd" au format français "dd/mm/YYYY"
   */
  static function to_datetime(?string $mydate, bool $with_seconds=true): ?string {
    if ($mydate === null) return null;
    $ms = null;
    if (self::is_date($mydate, $ms)) {
      return "$ms[3]/$ms[2]/$ms[1]";
    } elseif (self::is_datetime($mydate, $ms)) {
      if ($with_seconds) return "$ms[3]/$ms[2]/$ms[1] $ms[4]:$ms[5]:$ms[6]";
      else return "$ms[3]/$ms[2]/$ms[1] $ms[4]:$ms[5]";
    } else {
      return $mydate;
    }
  }

  /**
   * transformer une date sql "YYYY-mm-dd" au format français "dd/mm/YYYY"
   */
  static function to_date(?string $mydate): ?string {
    if ($mydate === null) return null;
    $ms = null;
    if (self::is_date($mydate, $ms)) return "$ms[3]/$ms[2]/$ms[1]";
    elseif (self::is_datetime($mydate, $ms)) return "$ms[3]/$ms[2]/$ms[1]";
    else return $mydate;
  }
}
