[Pas résolu] [SWIFT] Problème format date/heure

InsouInsou Membre
juin 2016 modifié dans API UIKit #1

Bonjour,


 


Je me confronte à  un nouveau problème et j'ai l'impression que je m'emmêle les pinceaux avec ces histoires de format de date, d'heure, de timezone, etc etc


 


Je ne pense pas que ce soit grand chose mais là  je commence à  tourner en rond..


 


Je vous explique mon problème..


 


J'utilise Eureka pour créer un composant "Time" qui me permet de choisir une heure précise..


Le problème c'est que l'heure affichée et l'heure récupérée n'est pas la même.. il y a un décalage de 2h..


 


Du coup, je me dis que c'est un soucis de timezone, de localisation ou un truc comme ça..


 


En gros, je sélectionne l'heure, exemple : 11h45


Et lors de la validation de mon formulaire, je récupère : 2016-06-28 09:45:13 +0000


 


Le code que j'opère dessus est le suivant :



let TabDate = String(laValeur).characters.split(" ").map(String.init)
print(TabDate[1]) // 09:45:13
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "HH:mm:ss"
dateFormatter.timeZone = NSTimeZone(abbreviation: "UTC") // ???
let heure = dateFormatter.dateFromString(String(TabDate[1]))
print(heure!) // 2000-01-01 09:46:32 +0000

Du coup, il y a surement un truc que j'ai mal saisis..


 


Comment gérez-vous les dates/heures pour les avoir la même que celle sélectionnée ?


Comment je peux gérer le décalage pour remettre l'heure exacte ?


 


Si quelqu'un peut m'éclairer, c'est pas de refus ^^


Merci de votre aide :)


Réponses

  • LarmeLarme Membre
    juin 2016 modifié #2

    NSDateComponents être la solution.


    Tu construis un NSDateComponents pour NSDate.date() (je suppose que c'est le jour qui t'intéresse) qu'on appellera finalDateComponents.


    Tu construis un NSDateComponents depuis let heure qu'on appellera heureDateComponents.


    Ensuite, tu transmets les valeurs des properties hour/minutes de heureDateComponents à  finalDateComponents.


    On est en +2 actuellement (heure d'été), donc 09:45:00+0000 est 11:45+2000 il me semble, à  moins que ça soit dans l'autre sens, je ne sais jamais. 


  • CéroceCéroce Membre, Modérateur
    Déjà , note que l'heure est tout à  fait exacte: en été, Paris a +2 h de décalage par rapport à  l'heure UTC. Donc 11:45 à  Paris correspond bien à  9:45 UTC.

    C'est à  l'affichage que la time zone aura de l'importance. Tu ne dois pas la fixer dans le NSDateFormatter. Par défaut, il utilise la defaultTimeZone, qui correspond à  celle de l'utilisateur.
  • InsouInsou Membre


    Déjà , note que l'heure est tout à  fait exacte: en été, Paris a +2 h de décalage par rapport à  l'heure UTC. Donc 11:45 à  Paris correspond bien à  9:45 UTC.


    C'est à  l'affichage que la time zone aura de l'importance. Tu ne dois pas la fixer dans le NSDateFormatter. Par défaut, il utilise la defaultTimeZone, qui correspond à  celle de l'utilisateur.




     


    Bah du coup, je risque d'avoir un autre soucis alors..


    Comment savoir sur quel fuseau horaire mon utilisateur se trouve ?


    Là  par exemple on est en UTC + 2h .. mais si mon utilisateur se trouve je ne sais où en UTC + 8h .. comment je peux le savoir ?


    En gros, je ne peux pas "corriger" ce décalage en dur dans mon code en ajoutant 2h à  l'heure que je récupère via le composant Time

  • CéroceCéroce Membre, Modérateur

    Comment savoir sur quel fuseau horaire mon utilisateur se trouve ?
    Là  par exemple on est en UTC + 2h .. mais si mon utilisateur se trouve je ne sais où en UTC + 8h .. comment je peux le savoir ?

    Justement, souvent, tu n'as pas besoin de le savoir. Si tu notes dans ton agenda que tu as un RDV téléphonique à  10:00, heure de Paris, et que tu te déplaces à  Berlin, tu as maintenant rendez-vous à  11:00. C'est pour cela qu'on utilise une heure universelle. La date est la même, c'est son affichage qui est différent.

    En gros, je ne peux pas "corriger" ce décalage en dur dans mon code en ajoutant 2h à  l'heure que je récupère via le composant Time

    Tout dépend de ce à  quoi sert l'heure. Par exemple, pour un réveil, tu veux te réveiller à  8:00, heure locale. Tu peux faire 13h d'avion, tu veux toujours que le réveil sonne à  8:00 heure locale. Dans ces cas-là , il faut utiliser NSDateComponents comme indiqué par Larme.
  • InsouInsou Membre

    Ok je comprends un peu mieux, par contre, je ne suis pas sûr d'être dans ce genre de cas..


     


    En gros, j'ai un formulaire, à  un moment il y a un champ "Heure", à  la selection, je choisir 13h30 et quand je récupère la valeur de mon formulaire, je me retrouve avec 2016-06-28 11:30:00 +0000 


    De ce que je comprends, c'est l'heure universel..


     


    Je veux récupérer l'heure sélectionnée à  la base (donc 13h30) et l'enregistrer dans une base de donnée..


    Le plus simple et fiable m'a l'air de récupérer l'heure universel et de faire le traitement côté php (pour récupérer 13h30 via les fuseaux horaires) et voila !


     


    En faisant le test, ça fonctionne bien :



    $utc = DateTime::createFromFormat(
    'H:i:s',
    $Time, // 11:30
    new DateTimeZone("UTC")
    );

    $HeureParis = $utc;
    $HeureParis->setTimeZone(new DateTimeZone('Europe/Paris'));

    echo $HeureParis->format('H:i'); // 13:30

    Bon du coup je récupère bien ce que je veux, je pense pouvoir m'en sortir pour la suite ;)


     


    Merci à  vous 2 pour l'aide et les explications 


  • LarmeLarme Membre

    De mémoire, il faut que tu dises à  ton NSDateFormatter que l'heure (en string) qu'il va traiter va être à  l'heure localisée française. Ce qui est ce que remplit l'utilisateur. Lui te le transformera ensuite en NSDate qui est en soit qu'un unixtimestamp wrappé dans un bel objet NSDate.


  • InsouInsou Membre

    En fait là  je me confronte à  un problème beaucoup plus compliqué qu'il ne devrait.. à  la base je ne veux pas m'occuper de fuseau horaire etc etc.. je veux juste que l'heure que je récupère visuellement, soit la même que celle qui est renvoyé quand je valide mon formulaire..


     


    Du coup, ma solution plus haut en gérant ça du côté php, ne convient pas, même si elle fonctionne..


     


    Je suis en train de faire quelques tests, juste pour que l'heure sélectionnée soit en accord avec l'heure renvoyée.. si ça fonctionne, je viens poster la solution ^^


  • CéroceCéroce Membre, Modérateur

    En fait là  je me confronte à  un problème beaucoup plus compliqué qu'il ne devrait..

    C'est toujours le cas quand on travaille avec les dates et heures.
    Si c'est simple, c'est qu'on n'y a pas réfléchi. En général, quand je demande à  un client sur quel fuseau horaire est son serveur, ils me répond "euh... je ne sais pas".
    (Non, je plaisante, en vrai, il me dit d'abord qu'il est sur le fuseau horaire de Paris, et il faut que je lui prouve que c'est faux).
  • InsouInsou Membre
    juillet 2016 modifié #10

     


    C'est toujours le cas quand on travaille avec les dates et heures.



     


    Ouai j'me doute, sauf que là , il n'y a aucune notion de fuseau..


    C'est comme si j'avais une facture et que l'heure d'achat était à  15h .. c'est tout ce dont j'ai besoin de savoir, du coup j'ai du bidouiller pour que le composant me retourne l'heure affiché et non l'heure UTC..


     


    Si ça peut aider/aiguiller certains un jour ou l'autre.. je post ça là ..


    Je tiens à  signaler que c'est plus une rustine qu'autre chose mais bon, pour le moment ça ira bien ^^


    Le code est placé à  la validation du formulaire, si c'est un item "TimeRow" alors on passe dans ce code pour ressortir l'heure affichée.



    // retourne UTC+décalage (ex: UTC+2)
    func getTimeZone() -> String{
    return NSTimeZone.localTimeZone().localizedName({
    return NSTimeZone.localTimeZone().daylightSavingTime ? NSTimeZoneNameStyle.ShortDaylightSaving : NSTimeZoneNameStyle.ShortStandard }(), locale: NSLocale.currentLocale()) ?? ""
    }


    let TabDate = String(laValeur).characters.split(" ").map(String.init) // recup l'heure du composant (-2 car UTC) // 2016-06-28 13:50:41 +0000
    let MyTimeZone = self.getTimeZone().stringByReplacingOccurrencesOfString("UTC", withString: "") // récupère le décalage UTC en supprimant UTC de la chaine // +2

    let dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "HH:mm:ss"
    dateFormatter.timeZone = NSTimeZone(abbreviation: "UTC")
    let heure = dateFormatter.dateFromString(String(TabDate[1]))

    let DateHeureCorrigée = NSCalendar.currentCalendar().dateByAddingUnit(
    .Hour,
    value: Int(MyTimeZone)!,
    toDate: heure!,
    options: [])
    print(DateHeureCorrigée!) // 2000-01-01 15:50:41 +0000

    let TabDateHeureCorrigée = String(DateHeureCorrigée).characters.split(" ").map(String.init)
    let TabHeureCorrigée = TabDateHeureCorrigée[1].characters.split(":").map(String.init)
    let HeureCorrigée = TabHeureCorrigée[0]+":"+TabHeureCorrigée[1]
    print(HeureCorrigée) // 15:50

    pfiouf, c'est résolu :)


     


     


    ////////// EDIT

    Solution plus simple et carrément plus fiable que cette rustine ici :
     http://forum.cocoacafe.fr/topic/14714-pas-résolu-swift-problème-avec-une-regex/?p=141908#12


  • En fait il faut te dire que l'heure que ton utilisateur saisi est un moment unique dans le temp, mais que ce moment a plusieurs représentations suivant le fuseau horaire. Il faut que tu utilises la même locale pour saisir cette heure et pour l'écrire dans un formulaire par la suite.

    Par contre, pour le système ce sera toujours représenté en UTC (si tu fais un affichage sans préciser la locale).
  • Ouai c'est ce que j'avais compris avec les réponses précédentes.. le truc c'est que c'était "trop" pour l'utilisation que j'en ai derrière, en gros je voulais juste récupérer l'heure qui était affiché dans le composant, au même format..


     


    Mais je comprends très bien ce que tu veux dire et j'en aurai surement besoin quand je devrais gérer des dates/heures d'une façon plus "normale" ;)


Connectez-vous ou Inscrivez-vous pour répondre.