[Catégorie modifiée .Net -> VBA] Appliquer un décalage automatique sur une date [Résolu]

pitipilot 111 Messages postés mercredi 19 mai 2010Date d'inscription 2 juin 2015 Dernière intervention - 10 mai 2011 à 16:55 - Dernière réponse : cs_cheyenne 693 Messages postés samedi 18 mai 2002Date d'inscription 17 avril 2017 Dernière intervention
- 11 mai 2011 à 22:02
Bonjourà tous, voilà j'ai un problème car mes champs de ma BDD sont en heures UTC et j'aimerais que lors de mes requêtes via VBA, celles ci soit en heures locales. Voici mon code :

Private Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type

Private Type TIME_ZONE_INFORMATION
Bias As Long
StandardName(0 To 31) As Integer
StandardDate As SYSTEMTIME
StandardBias As Long
DaylightName(0 To 31) As String * 64
DaylightDate As SYSTEMTIME
DaylightBias As Long
End Type
Private Declare Function SetTimeZoneInformation Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long
Private Declare Function GetTimeZoneInformation Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long

Public Function GetTimeZone() As String
Dim tZone As TIME_ZONE_INFORMATION
Dim lngret As Long
Dim i As Long


lngret = GetTimeZoneInformation(tZone)

For i = 0 To 31 ' the array's range is from 0 to 31'
If tZone.StandardName(i) = 0 Then Exit For

Next


End Function

Private Sub Workbook_Open()

Dim lngret As Long
Dim derniere_ligne As Integer
Dim j As Integer
Dim sj As String
Dim Decalage As Integer
Dim sDate_gmt As Date
Dim tZone As TIME_ZONE_INFORMATION



Decalage = CInt(GetTimeZoneInformation(tZone))


derniere_ligne = Range("I2").SpecialCells(xlCellTypeLastCell).Row 'acquisition dernière ligne colonne I'
 

For j = 2 To derniere_ligne   'début boucle For'

sj = CStr(j) 'conversion entier en string'



sDate_gmt = Range("I" + sj).Value + Decalage / 24


Range("I" + sj).Value = sDate_gmt

Next
End Sub


Voilà donc je récupère le décalage horaire (1h en heure d'hiver et 2 en heures d'été). J'ajoute ce décalage à mes dates et hop nikel sauf que...
Si je vais récupérer des enregistrements de ma BDD datant de l'heure d'hiver maintenant je vais ajouter 2 heures et vice versa.

Comment pouvoir convertir automatiquement une DateTime avec le décalage horaire qui lui correspond ?
Afficher la suite 

33 réponses

Répondre au sujet
cs_Jack 14010 Messages postés samedi 29 décembre 2001Date d'inscription 28 août 2015 Dernière intervention - 11 mai 2011 à 00:43
+3
Utile
Non, non et non.
Les APIs savent renvoyer le décalage d'une date sans être obligé de se tartiner les calculs de dates.
De plus, les fonctions DateAdd et DateDiff sont là pour se simplifier la vie. Pourquoi vouloir passer par des Double - trop compliqué.

Exemple simple de conversion :
Public Function ConvertUtcTimeToLocalTime(ByVal UtcDateTime As Date) As Date
    ' L'heure fournie est exprimée en UTC et au format du système
    ' L'heure renvoyée sera exprimée en heure locale, et toujours au format du système
    ' Accepte n'importe quel format de date du moment que ce format est le format de l'OS
    Dim tzi         As TIME_ZONE_INFORMATION
    Dim UtcTime     As SYSTEMTIME
    Dim LocalTime   As SYSTEMTIME
    
    Call GetTimeZoneInformation(tzi)
    With UtcTime
        .wDay = Day(UtcDateTime)
        .wMonth = Month(UtcDateTime)
        .wYear = Year(UtcDateTime)
        .wHour = Hour(UtcDateTime)
        .wMinute = Minute(UtcDateTime)
        .wSecond = Second(UtcDateTime)
    End With
    
    Call SystemTimeToTzSpecificLocalTime(tzi, UtcTime, LocalTime)
    
    With LocalTime
        ConvertUtcTimeToLocalTime = CDate(DateSerial(.wYear, .wMonth, .wDay) & _
                                          " " & _
                                          TimeSerial(.wHour, .wMinute, .wSecond))
    End With
End Function
Bien sûr, il faut ajouter les déclarations qui vont bien, mais comme je te l'ai déjà dit, ces exemples existent dans http://logiciel.codes-sources.com/logiciels/API-Guide-197.aspx + un tout petit peu de temps pour comprendre et faire des essais
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_Jack
cs_cheyenne 693 Messages postés samedi 18 mai 2002Date d'inscription 17 avril 2017 Dernière intervention - 11 mai 2011 à 13:04
+3
Utile
Bonjour,

Oui, il y a une solution et c'est celle de jack.
Je t'ai un peu embrouillé avec mon idée car je ne connaissais pas cette API, d'où cette idée de comparer les dates. Donc pas de tartinage de dates (dixit jack )

Pour ton erreur as-tu bien verifié si TIME_ZONE_INFORMATION et SYSTEMTIME sont bien formulés de la même façon dans les déclarations de Type et les API. L'erreur provient peut-être de là.

Pour obtenir la date convertie :
Tu extrais la date et l'heure UTC de ta base,
puis tu appelles la fonction qui te renvoie en retour la date et l'heure en temps local.
UtcDateTime = (extraite de la BDD)
TempsLocal = ConvertUtcTimeToLocalTime(ByVal UtcDateTime As Date) As Date

Il faut que la date envoyée soit dans un des formats de Windows et la date en retour sera au format que tu utilises.

Ne t'inquiètes pas pour tes questions, le forum est là pour cela.

Cheyenne







Cheyenne
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_cheyenne
cs_Jack 14010 Messages postés samedi 29 décembre 2001Date d'inscription 28 août 2015 Dernière intervention - 10 mai 2011 à 18:29
0
Utile
Salut

Une fois que tu auras récupéré le décalage (en général en minutes), voir les fonctions adéquates pour opérations sur les dates : DateAdd et DateDiff

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
Commenter la réponse de cs_Jack
cs_cheyenne 693 Messages postés samedi 18 mai 2002Date d'inscription 17 avril 2017 Dernière intervention - 10 mai 2011 à 19:06
0
Utile
Bonjour,

> Bonjour Jack. Non ce n'est pas des minutes.
C'est 1 ou 2 heures que renvoie GetTimeZoneInformation()

> Bonjour pitipilot. Je croyais que le problème était résolu !
Je t'avais signalé ce problème dans un précédent post : pour avoir une heure locale correcte il faut tenir compte des deux périodes Hiver/Eté, il faut donc déterminer dans quelle période se situe la date UTC.

Pour ce faire utilises DateSerial qui te renvoie un numéro d'ordre représentant la date série pour une année, un mois et jour déterminés.
Il te faut 3 variables, debHiver, finHiver, et
jour_data.
debHiver pour le début de la période hiver et finHiver pour la fin.
jour_data est la date à convertir.
Si jour_data est compris dans l'intervalle debHiver/finHiver tu rajoutes 1 heure sinon 2.

Cheyenne
Commenter la réponse de cs_cheyenne
cs_cheyenne 693 Messages postés samedi 18 mai 2002Date d'inscription 17 avril 2017 Dernière intervention - 10 mai 2011 à 19:19
0
Utile
Re,

Attention, il ne faut pas que tes dates à convertir soient trop vieilles, actuellement si pas Hiver en cours tu rajoutes 2. Donc période Eté, mais si c'est trop vieux tu risques de tomber dans la période Hiver d'une autre année.
Si c'est la cas il faut en fonction de l'année des dates à convertir calculer les DateSerial des périodes et non pas leur indiquer une date formelle. C'est ce qu'il faut faire si ton programme est appelé à resservir l'année prochaine.

Comme déjà indiqué, n'utilises pas GMT, c'est périmé depuis 1972 !!!! voir mes précédents post.
http://www.vbfrance.com/forum/sujet-CONVERTIR-HEURE-UTC-HEURE-GMT-VBA_1517549.aspx?p=2

Cheyenne
Commenter la réponse de cs_cheyenne
cs_cheyenne 693 Messages postés samedi 18 mai 2002Date d'inscription 17 avril 2017 Dernière intervention - 10 mai 2011 à 19:27
0
Utile
Re,

Dernière précision, tu n'as plus besoin des API puisque, selon une période donnée, tu rajoutes 1 ou 2 heures.
Tu ne ferais que du temps réel, là il faudrait les API, car cela irait plus vite que de déterminer dans quelle période tombe la date UTC de tous tes enregistrements.

Cheyenne
Commenter la réponse de cs_cheyenne
cs_cheyenne 693 Messages postés samedi 18 mai 2002Date d'inscription 17 avril 2017 Dernière intervention - 10 mai 2011 à 19:45
0
Utile
Re,

C'est encore moi !
Il faut multiplier DateSerial par 1 pour avoir un numéro et pas une date.
Attention, si la date d'un enregistrement se situe le jour du changement de période, mais entre 00.00 et 03.00, le calcul sera faussé.
Donc pour plus de sécutité :
tes 3 variables seront du type double et au lieu de DateSerial(yy,mm,dd) *1 tu fais :
debHiver = DateSerial(yy,mm,dd) * 1 + TimeSerial(h,m,s) * 1

ce qui te donne une valeur du genre 40821.8211805556 pour le 10/05/11 à 19:42:30

Ainsi le doute sera levé qunat à la bonne période de ce jour.

Cheyenne
Commenter la réponse de cs_cheyenne
cs_cheyenne 693 Messages postés samedi 18 mai 2002Date d'inscription 17 avril 2017 Dernière intervention - 10 mai 2011 à 19:51
0
Utile
Re, Re, etc...

A la date debHiver et debEte tu rajoutes 0.125 car c'est à partir de 3 heures du matin que le changement est effectif.

Voilà, je crois que j'ai tout dit

Cheyenne
Commenter la réponse de cs_cheyenne
pitipilot 111 Messages postés mercredi 19 mai 2010Date d'inscription 2 juin 2015 Dernière intervention - 10 mai 2011 à 19:51
0
Utile
Oula ça fais beaucoup d'un coup ^^. Bah les informations à traiter devront être sauvegarder durant 7ans. Selon ta méthode il faut calculer les dates serials pour chaque année. Sauf que mon système doit être autonome pour les années à venir =S. Mais j'y pense, c'est pas possible dans SQL d'appliquer l'heure locale sur les TimeStamps comme ça on en reparlerais plus ^^. Bonne soirée et merci de votre aide.
Commenter la réponse de pitipilot
cs_cheyenne 693 Messages postés samedi 18 mai 2002Date d'inscription 17 avril 2017 Dernière intervention - 10 mai 2011 à 19:53
0
Utile
Heu,désolé

Je rectifie, il fallait bien sur lire :
debHiver et finHiver

Cheyenne
Commenter la réponse de cs_cheyenne
cs_cheyenne 693 Messages postés samedi 18 mai 2002Date d'inscription 17 avril 2017 Dernière intervention - 10 mai 2011 à 22:49
0
Utile
Re,

Ben oui, tu es obligé d'en passer par là pour avoir une heure locale juste puisque tu n'est pas en temps réel.
Pour être autonome, il suffit de calculer le dernier dimanche d'Octobre de l'année précédant l'enregistrement et le dernier dimanche de Mars de l'année de l'enregistrement.
Par exemple, si date UTC du 18/03/05, calculer le dernier Dimanche d'Octobre 2004 et le dernier Dimanche de Mars 2005 pour avoir la période Hiver. Donc heure locale = UTC + 1. Si date du 20/07/05 UTC + 2. CQFD

Le plus pratique serait, si possible, de convertir au moment de l'enregistrement du timestamp l'heure UTC en locale.

Je ne pratique pas le SQL mais si tu veux convertir les dates de ta BDD on en revient au problème précédent.

Cheyenne
Commenter la réponse de cs_cheyenne
pitipilot 111 Messages postés mercredi 19 mai 2010Date d'inscription 2 juin 2015 Dernière intervention - 11 mai 2011 à 08:06
0
Utile
Bah il n'y aurait pas le même problème puisque précédemment nous avons dévelloppé un code permettant de calculer le décalage horaire en temps réel. Si en SQL je peux utiliser cette fonction et l'appliquer directement sur les timestamps rentrant alors ça faciliterait grandement les choses. Surtout que sinon vu que je veux effectuer des tri par date, il faudra que je touche à la requête à chaque fois.
Commenter la réponse de pitipilot
pitipilot 111 Messages postés mercredi 19 mai 2010Date d'inscription 2 juin 2015 Dernière intervention - 11 mai 2011 à 09:01
0
Utile
Désolé Jack j'avais pas vu ton post ^^. Si avec ta manière on peut convertir la date automatiquement tu m'enlève une sacré épine du pied.

Par contre dans ton code je n'ai pas trop compris où insérer la date d'entrée et où récupérer celle de sortie.

Les API GUIDE sons super pratique mais je ne peux pas les tester car j'ai un message d'erreur.
Commenter la réponse de pitipilot
pitipilot 111 Messages postés mercredi 19 mai 2010Date d'inscription 2 juin 2015 Dernière intervention - 11 mai 2011 à 10:06
0
Utile
Sinon j'ai trouvé ça sur le net :

' Convert a Date into a SYSTEMTIME.
Private Sub DateToSystemTime(ByVal the_date As Date, ByRef _
    system_time As SYSTEMTIME)
    With system_time
        .wYear = Year(the_date)
        .wMonth = Month(the_date)
        .wDay = Day(the_date)
        .wHour = Hour(the_date)
        .wMinute = Minute(the_date)
        .wSecond = Second(the_date)
    End With
End Sub

' Convert a SYSTEMTIME into a Date.
Private Sub SystemTimeToDate(system_time As SYSTEMTIME, _
    ByRef the_date As Date)
    With system_time
        the_date = DateSerial(.wYear, .wMonth, .wDay) + _
                   TimeSerial(.wHour, .wMinute, .wSecond)
    End With
End Sub

' Convert a UTC time into local time.
Private Function UTCToLocalTime(ByVal the_date As Date) As _
    Date
Dim system_time As SYSTEMTIME
Dim local_file_time As FILETIME
Dim utc_file_time As FILETIME

    ' Convert it into a SYSTEMTIME.
    DateToSystemTime the_date, system_time

    ' Convert it to a UTC time.
    SystemTimeToFileTime system_time, utc_file_time

    ' Convert it to a FILETIME.
    FileTimeToLocalFileTime utc_file_time, local_file_time

    ' Convert it to a SYSTEMTIME.
    FileTimeToSystemTime local_file_time, system_time

    ' Convert it to a Date.
    SystemTimeToDate system_time, the_date

    UTCToLocalTime = the_date
End Function


Et là même problème la valeur d'entrée je suppose que c'est "the_date" mais après comment récupéré la valeur en localtime?
Commenter la réponse de pitipilot
cs_cheyenne 693 Messages postés samedi 18 mai 2002Date d'inscription 17 avril 2017 Dernière intervention - 11 mai 2011 à 11:41
0
Utile
Bonjour,

> Jack, Bravo, je ne connaissais pas l'API SystemTimeToTzSpecificLocalTime qui n'est pas listée sur le site de AllAPI.
Voilà qui simplifie grandement le problème de notre ami.

> pitipilot, suis les conseils de jack et utilise son code que je me suis empressé de tester. Non par doute, bien sûr, mais pour l'expérimenter. Impeccable, tu n'as plus à te soucier de la période Hiver/Ete.

J'ai déclaré l'API comme ceci :
Private Declare Function SystemTimeToTzSpecificLocalTime Lib "kernel32" ( _
        TimeZone As TIME_ZONE_INFORMATION, _
        tempsUTC As SYSTEMTIME, _
        tempsLOCAL As SYSTEMTIME _
        ) As Long 

Jack, tu me diras, stp, si cela est conforme. En tous cas ça fonctionne correctement.

Cheyenne
Commenter la réponse de cs_cheyenne
pitipilot 111 Messages postés mercredi 19 mai 2010Date d'inscription 2 juin 2015 Dernière intervention - 11 mai 2011 à 12:19
0
Utile
J'ai testé le code que j'avais trouvé sur le net et j'ai eu le même résultat
Concernant le code de Jack :

Private Declare Function SystemTimeToTzSpecificLocalTime Lib "kernel32" ( _
        TimeZone As TIME_ZONE_INFORMATION, _
        tempsUTC As SYSTEMTIME, _
        tempsLOCAL As SYSTEMTIME _
        ) As Long



Public Function ConvertUtcTimeToLocalTime(ByVal UtcDateTime As Date) As Date
    ' L'heure fournie est exprimée en UTC et au format du système
    ' L'heure renvoyée sera exprimée en heure locale, et toujours au format du système
    ' Accepte n'importe quel format de date du moment que ce format est le format de l'OS
    Dim tzi         As TIME_ZONE_INFORMATION
    Dim UtcTime     As SYSTEMTIME
    Dim LocalTime   As SYSTEMTIME
    
    Call GetTimeZoneInformation(tzi)
    With UtcTime
        .wDay = Day(UtcDateTime)
        .wMonth = Month(UtcDateTime)
        .wYear = Year(UtcDateTime)
        .wHour = Hour(UtcDateTime)
        .wMinute = Minute(UtcDateTime)
        .wSecond = Second(UtcDateTime)
    End With
    
    Call SystemTimeToTzSpecificLocalTime(tzi, UtcTime, LocalTime)
    
    With LocalTime
        ConvertUtcTimeToLocalTime = CDate(DateSerial(.wYear, .wMonth, .wDay) & _
                                          " " & _
                                          TimeSerial(.wHour, .wMinute, .wSecond))
    End With
End Function


Lorsque j'essaye de lui affectuer une macro j'ai un message d'erreur : "Erreur de compilation : Type défini par l'utilisateur non défini"

Dois-je rajouter une référence ? Si oui laquelle?

Et par contre désolé de mes question de débutant mais je ne vois pas ensuite comment affecter à ce code une valeur d'entrée et récupérer une valeur de sortie.

En tout cas c'est rassurant de savoir qu'il existe des solutions.
Commenter la réponse de pitipilot
cs_Jack 14010 Messages postés samedi 29 décembre 2001Date d'inscription 28 août 2015 Dernière intervention - 11 mai 2011 à 14:49
0
Utile
Tu as cette erreur parce que tes déclarations sont incomplètes.
Il te faut déclarer les types de structure comme SYSTEMTIME
Je pensais que tu avais lu quelques sources et donc, déjà rencontreé ce genre d'utilisation des APIs.
Quand tu as des recherches à faire sur une fonction ou variable que tu ne connais pas, il te suffit de taper "VB " suivi du nom de la fonction/variable pour trouver des exemples de codes sur le net.

Déclarations nécessaires :
Private Type TIME_ZONE_INFORMATION
    Bias                As Long
    StandardName(32)    As Integer
    StandardDate        As SYSTEMTIME
    StandardBias        As Long
    DaylightName(32)    As Integer
    DaylightDate        As SYSTEMTIME
    DaylightBias        As Long
End Type
Private Type SYSTEMTIME
    wYear               As Integer
    wMonth              As Integer
    wDayOfWeek          As Integer
    wDay                As Integer
    wHour               As Integer
    wMinute             As Integer
    wSecond             As Integer
    wMilliseconds       As Integer
End Type
'   http://msdn.microsoft.com/en-us/library/ms724421%28VS.85%29.aspx
Private Declare Function GetTimeZoneInformation Lib "Kernel32" (ByRef TimeZoneInfo As TIME_ZONE_INFORMATION) As Long
'   http://msdn.microsoft.com/en-us/library/ms724949%28v=VS.85%29.aspx
Private Declare Function SystemTimeToTzSpecificLocalTime Lib "Kernel32" (ByRef TimeZoneInfo As TIME_ZONE_INFORMATION, ByRef UTC_Time As SYSTEMTIME, ByRef Local_Time As SYSTEMTIME) As Long

Côté utilisation de la fonction que je t'ai proposée :
Dim maDate As Date
maDate = Now
MsgBox "Heure UTC : " & ConvertUtcTimeToLocalTime(maDate)

Une fonction renvoie une valeur dont le type est défini dans le dernier paramètre "As Date" de définition de la fonction.

Pour ajouter au dernier commentaire de Cheyenne, lors de l'utilisation/l'appel de la fonction, il n'est pas nécessaire (autorisé ?) de répéter le type de la variable.
Le ByVal (et son copain ByRef) permettent de définir si ce n'est que la valeur qui est transmise (ByVal Entrée seule) ou bien si c'est l'adresse de la variable (ByRef Entrée et Sortie). Cette dernière utilisation est plus rapide (pouillième) mais offre l'avantage que, si le contenu de la variable est modifié dans la fonction, elle sera elle aussi renvoyée au code appelant. Cela permet de 'redescendre' plus de valeurs résultats d'une fonction.

Des notions à bien comprendre, surtout si on veut utiliser et comprendre l'appel des APIs.

Pour ta database, il est impératif que tu gardes les heures au format UTC. D'une part parce que l'industrie n'accepterait pas que les données soient bidouillées avant d'être enregistrées (moins de bidouillage = plus de sureté de la donnée), et d'autre part parce que les heures UTC garantissent l'heure exact de l'évènement sans aucun doute possible sur l'heure d'hiver ou d'été.
Il te faut simplement convertir chaque date que tu devras aller rechercher dans ta table, au format UTC, et c'est là que des questions peuvent être posées à l'utilisateur au cas où la date de recherche qu'il demande est dans un créneau horaire du jour des changements (surtout entre 1h et 2h UTC fin octobre où nous 'vivons' deux fois la même heure)

Puisque ce n'est pas tous les jours mercredi, je te fais le cadeau supplémentaire suivant : la fonction inverse : Local -> UTC
Cela te sera utile pour retrouver tes enregistrements et questionner ta DB.
Déclaration supplémentaire :
'   http://msdn.microsoft.com/en-us/library/ms725485%28v =VS.85%29.aspx
Private Declare Function TzSpecificLocalTimeToSystemTime Lib "Kernel32" (ByRef TimeZoneInfo As TIME_ZONE_INFORMATION, ByRef Local_Time As SYSTEMTIME, ByRef UTC_Time As SYSTEMTIME) As Long

Fonction :
Public Function ConvertLocalTimeToUtcTime(ByVal LocalDateTime As Date) As Date

    ' L'heure fournie est exprimée en heure locale et au format du système
    ' L'heure renvoyée sera exprimée en UTC, et toujours au format du système
    ' Accepte n'importe quel format de date du moment que ce format est le format de l'OS
    
    Dim tzi         As TIME_ZONE_INFORMATION
    Dim UtcTime     As SYSTEMTIME
    Dim LocalTime   As SYSTEMTIME
    
    Call GetTimeZoneInformation(tzi)
    With LocalTime
        .wDay = Day(LocalDateTime)
        .wMonth = Month(LocalDateTime)
        .wYear = Year(LocalDateTime)
        .wHour = Hour(LocalDateTime)
        .wMinute = Minute(LocalDateTime)
        .wSecond = Second(LocalDateTime)
    End With
    
    Call TzSpecificLocalTimeToSystemTime(tzi, LocalTime, UtcTime)
    
    With UtcTime
        ConvertLocalTimeToUtcTime = CDate(DateSerial(.wYear, .wMonth, .wDay) & _
                                          " " & _
                                          TimeSerial(.wHour, .wMinute, .wSecond))
    End With
    
End Function
Commenter la réponse de cs_Jack
cs_Jack 14010 Messages postés samedi 29 décembre 2001Date d'inscription 28 août 2015 Dernière intervention - 11 mai 2011 à 14:58
0
Utile
Jour de bonté.
Il faut savoir que les champs de type Date sont mémorisées dans les databases au format US, c'est à dire Mois/Jour/Année.
Pour t'éviter de nouveaux nœuds au cerveau, voilà une autre fonction maison qui permet de récupérer une chaine au format US à partir d'une date, locale ou UTC, peu importe, il n'y a pas de conversion, juste une correction du format.
Déclarations :
Private Const LOCALE_SYSTEM_US          As Long = 1033
Private Const LOCALE_SYSTEM_FRENCH      As Long = 1036
Private Const LOCALE_SYSTEM_JAPAN       As Long = 1041
Private Const LOCALE_NOUSEROVERRIDE     As Long =  &H80000000
'   http://msdn.microsoft.com/en-us/library/dd318086%28VS.85%29.aspx
Private Declare Function GetDateFormat Lib "Kernel32" Alias "GetDateFormatA" (ByVal Locale As Long, ByVal dwFlags As Long, lpDate As SYSTEMTIME, ByVal lpFormat As String, ByVal lpDateStr As String, ByVal cchDate As Long) As Long

Fonction :
Public Function FormatSQLDateTimeString(OsFormatedDate As Date) As String
    
    ' Convertit une date/heure en date générale internationale (US) : Mois/Jour/Année
    ' Accepte n'importe quel format de date du moment que ce format est le format de l'OS
    
    Dim mDate   As SYSTEMTIME
    Dim sBuffer As String
    Dim r       As Long
    
    With mDate
        .wDay  = Day(OsFormatedDate)
        .wMonth = Month(OsFormatedDate)
        .wYear = Year(OsFormatedDate)
        .wHour = Hour(OsFormatedDate)
        .wMinute = Minute(OsFormatedDate)
        .wSecond = Second(OsFormatedDate)
    End With
    
    ' Date
    sBuffer = String(255, 0)
    r = GetDateFormat(LOCALE_SYSTEM_US, DATE_SHORTDATE, mDate, vbNullString, sBuffer, Len(sBuffer))
    If r > 0 Then
        FormatSQLDateTimeString = Left$(sBuffer, r - 1)
    Else
        Debug.Print Time, "(FormatSQLDateTimeString - date) La fonction renvoie " & CStr(r)
    End If
    
    ' Heure
    sBuffer = String(255, 0)
    r = GetTimeFormat(LOCALE_SYSTEM_US, LOCALE_NOUSEROVERRIDE, mDate, vbNullString, sBuffer, Len(sBuffer))
    If r > 0 Then
        FormatSQLDateTimeString = FormatSQLDateTimeString & " " & Left$(sBuffer, r - 1)
    Else
        Debug.Print Time, "(FormatSQLDateTimeString - heure) La fonction renvoie " & CStr(r)
    End If
    
End Function
Commenter la réponse de cs_Jack
pitipilot 111 Messages postés mercredi 19 mai 2010Date d'inscription 2 juin 2015 Dernière intervention - 11 mai 2011 à 15:00
0
Utile
Nikel ça marche voici mon code pour ceux qui auraient le même problème :

Private Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type

Private Type TIME_ZONE_INFORMATION
Bias As Long
StandardName(0 To 31) As Integer
StandardDate As SYSTEMTIME
StandardBias As Long
DaylightName(0 To 31) As String * 64
DaylightDate As SYSTEMTIME
DaylightBias As Long
End Type
Private Declare Function SetTimeZoneInformation Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long
Private Declare Function GetTimeZoneInformation Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long


Private Declare Function SystemTimeToTzSpecificLocalTime Lib "kernel32" ( _
        TimeZone As TIME_ZONE_INFORMATION, _
        tempsUTC As SYSTEMTIME, _
        TempsLocal As SYSTEMTIME _
        ) As Long



Public Function ConvertUtcTimeToLocalTime(ByVal UtcDateTime As Date) As Date
    ' L'heure fournie est exprimée en UTC et au format du système
    ' L'heure renvoyée sera exprimée en heure locale, et toujours au format du système
    ' Accepte n'importe quel format de date du moment que ce format est le format de l'OS
    Dim tzi         As TIME_ZONE_INFORMATION
    Dim UtcTime     As SYSTEMTIME
    Dim LocalTime   As SYSTEMTIME
    
    Call GetTimeZoneInformation(tzi)
    With UtcTime
        .wDay = Day(UtcDateTime)
        .wMonth = Month(UtcDateTime)
        .wYear = Year(UtcDateTime)
        .wHour = Hour(UtcDateTime)
        .wMinute = Minute(UtcDateTime)
        .wSecond = Second(UtcDateTime)
    End With
    
    Call SystemTimeToTzSpecificLocalTime(tzi, UtcTime, LocalTime)
    
    With LocalTime
        ConvertUtcTimeToLocalTime = CDate(DateSerial(.wYear, .wMonth, .wDay) & _
                                          " " & _
                                          TimeSerial(.wHour, .wMinute, .wSecond))
    End With
End Function

Sub Bouton3()
Dim UtcDateTime As Date
Dim TempsLocal As Date

 UtcDateTime = Range("A8").Value 'date UTC'
TempsLocal = ConvertUtcTimeToLocalTime(UtcDateTime) 'Date locale'

End Sub


Merci beaucoup à vous deux, ça marche parfaitement . Il me reste juste une dernière question, étant donné que je fais un tri dans ma BDD par date, il faut que je convertisse cette date locale en UTC pour que les dates et heures soient cohérentes. Que dois-je modifier dans le code ci-dessus pour faire l'inverse c'est à dire passer d'une date heure locale à une date heure UTC?
Commenter la réponse de pitipilot
cs_Jack 14010 Messages postés samedi 29 décembre 2001Date d'inscription 28 août 2015 Dernière intervention - 11 mai 2011 à 15:00
0
Utile
J'ai oublié cette déclaration :
Public Enum eDateFormat
    DATE_LONGDATE = &H2       ' mercredi 24 février 2010
    DATE_SHORTDATE = &H1      ' 24/02/2010
End Enum
Commenter la réponse de cs_Jack

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.

[Catégorie modifiée .Net -> VBA] Appliquer un décalage automatique sur une date - page 2