[C#] NHibernate en >= of <= met TimeSpan

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Ik zit met een raar probleem met NHibernate. Als ik vergelijkingen ga uitvoeren op een TimeSpan dan krijg ik het volgende probleem:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
-------------------------------------------------------------------------------------
could not execute query
<SNIP>
Positional parameters:  #0>19:00:00
<SNIP>
-------------------------------------------------------------------------------------
   at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes)
   at NHibernate.Loader.Criteria.CriteriaLoader.List(ISessionImplementor session)
   at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results)
   at NHibernate.Impl.CriteriaImpl.List(IList results)
   at NHibernate.Impl.CriteriaImpl.List[T]()
<SNIP>
-------------------------------------------------------------------------------------
The data types time and datetime are incompatible in the greater than or equal to operator.
-------------------------------------------------------------------------------------
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()
   at NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand cmd)
   at NHibernate.Loader.Loader.GetResultSet(IDbCommand st, Boolean autoDiscoverTypes, Boolean callable, RowSelection selection, ISessionImplementor session)
   at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
   at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
   at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)


De query is 100% goed, getest in SQL Server. Het probleem blijkt te liggen in de manier hoe .NET omgaat met Time parameters... ;(

http://connect.microsoft....instead-of-sqldbtype-time
quote: Microsoft
Thanks for reporting this issue. This is a bug in our product, but after carefully investigating the issue, we have decided not to fix the bug. Fixing this bug will cause a breaking change and in most of customer scenarios, they should be able to use SqlParameter.SqlDbType. Please let us know if this is a blocking issue for some of your major scenarios.
Ik kan dus wachten tot ik een ons weeg :F
Natuurlijk ben ik niet de enige met dit probleem:

http://osdir.com/ml/nhibe...ent/2010-06/msg00095.html

Dit is een "mooie" workaround maar ik zit er ook niet op te wachten om bij elke nieuwe versie van NHibernate deze fix in hun code te plakken, de boel te compileren om daarna te koppelen aan mijn eigen project.

Kent iemand dit probleem en zo ja, is er een mooiere manier om dit te op te lossen?

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • bastv
  • Registratie: September 2005
  • Laatst online: 23-06 10:03
heb je misschien code en mapping voorbeeld?
in de nh bugtracker staat er namelijk niets open over dit probleem.

http://216.121.112.228/secure/QuickSearch.jspa

Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Het code voorbeeld wat ik heb is erg generiek dus ik denk niet dat je daar wat aan hebt. Ik heb hieronder een concreet voorbeeld gemaakt:

code:
1
2
3
4
5
public static IList<T> ListEmployeesWhereStartingOnGreaterThan<T>(TimeSpan startingOn) {
     ICriteria criteria = session.CreateCriteria(typeof(T));
     ICriterion expr = Expression.Gt("StartingOn", startingOn);
     return IList<T> items = criteria.List<T>();
}


Als mapping property krijg je dan dit:

code:
1
<property name="StartingOn" column="[StartingOn]" type="TimeAsTimeSpan" />


Als je de onderstaande link bekijkt dan zie je dat Fabio van NHibernate reageert en er dus vanaf weet. Ik kan trouwens net als jij ook geen issue vinden... wel raar eigenlijk.

http://osdir.com/ml/nhibe...ent/2010-06/msg00095.html

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 23-06 11:51

Janoz

Moderator Devschuur®

!litemod

Misschien begrijp ik het niet helemaal, maar de hele essentie van een timespan is toch dat het een bepaalde tijdsduur aangeeft en dat het compleet los staat van het begin moment? Bij iets als 'startingOn' lijkt mij dan ook niet dat je dit type dat je daarvoor wilt gebruiken.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Janoz schreef op maandag 06 september 2010 @ 13:21:
Misschien begrijp ik het niet helemaal, maar de hele essentie van een timespan is toch dat het een bepaalde tijdsduur aangeeft en dat het compleet los staat van het begin moment? Bij iets als 'startingOn' lijkt mij dan ook niet dat je dit type dat je daarvoor wilt gebruiken.
Sorry voor het misverstand. Het gaat hiet niet om StartingOn in de zin van wanneer hij voor het eerst begonnen is met werken (datum / tijd) maar WANNEER hij elke dag begint met werken (dus bv 08:00).

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 23-06 11:51

Janoz

Moderator Devschuur®

!litemod

Dan nog is dat niet een TimeSpan. Een TimeSpan is niet een specifiek moment op de dag of in de tijd. Een TimeSpan is een lengte gemeten in tijd (aantal dagen, aantal uren, aantal seconden, enz enz). Een timespan gebruik je niet om aan te geven wanneer iemand begint, maar bijvoorbeeld hoe lang iemand op een dag werkt.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Janoz schreef op maandag 06 september 2010 @ 13:39:
Dan nog is dat niet een TimeSpan. Een TimeSpan is niet een specifiek moment op de dag of in de tijd. Een TimeSpan is een lengte gemeten in tijd (aantal dagen, aantal uren, aantal seconden, enz enz). Een timespan gebruik je niet om aan te geven wanneer iemand begint, maar bijvoorbeeld hoe lang iemand op een dag werkt.
Het gebruik van de Timespan lijkt me hier correct.
Het is de offset (tov 0:00) waarop je begint. Een datetime is een absolute tijd en hiervoor niet bruikbaar.

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 23-06 11:51

Janoz

Moderator Devschuur®

!litemod

Ik heb nog even door de msdn gebladerd, maar het lijkt me eerder een gebrek dat er geen tijd object is.

Uberhaupt het feit dat je als extra waarde een offset nodig hebt om te bepalen wat nu daadwerkelijk de betekenis is van de lengte zou wel een lichtje moeten laten branden dat er iets niet helemaal klopt. Daarnaast gaat het mis op het moment dat we van zomer naar wintertijd wisselen (en omgekeerd).

Een TimeSpan is een verschil tussen twee tijdstippen, niet een tijdstip op zichzelf.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
H!GHGuY schreef op maandag 06 september 2010 @ 13:59:
Het gebruik van de Timespan lijkt me hier correct.
Het is de offset (tov 0:00) waarop je begint. Een datetime is een absolute tijd en hiervoor niet bruikbaar.
Dat dacht ik dus ook maar als er een beter alternatief is dan hoor ik het graag. Ik maak btw gebruik van het Time type in SQL Server 2008 (in 2005 heb je alleen maar DateTime).
Janoz schreef op maandag 06 september 2010 @ 14:04:
Ik heb nog even door de msdn gebladerd, maar het lijkt me eerder een gebrek dat er geen tijd object is.

Uberhaupt het feit dat je als extra waarde een offset nodig hebt om te bepalen wat nu daadwerkelijk de betekenis is van de lengte zou wel een lichtje moeten laten branden dat er iets niet helemaal klopt. Daarnaast gaat het mis op het moment dat we van zomer naar wintertijd wisselen (en omgekeerd).

Een TimeSpan is een verschil tussen twee tijdstippen, niet een tijdstip op zichzelf.
Net ook even door MSDN gebladerd en volgens mij mag het wel:
quote: MSDN
A TimeSpan object represents a time interval (duration of time or elapsed time) that is measured as a positive or negative number of days, hours, minutes, seconds, and fractions of a second. The TimeSpan structure can also be used to represent the time of day, but only if the time is unrelated to a particular date.

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 23-06 11:51

Janoz

Moderator Devschuur®

!litemod

Maar ja, als de klok terug gaat van 3 naar 2 dan zit je 8u na middernacht toch nog echt pas op 7:00am

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Janoz schreef op maandag 06 september 2010 @ 14:16:
Maar ja, als de klok terug gaat van 3 naar 2 dan zit je 8u na middernacht toch nog echt pas op 7:00am
Werkt dat echt op die manier? Ik heb het net lokaal geprobeerd maar ik krijg het niet hergeproduceerd...

SQL:
1
select * from my_table


1. Bovenstaande query uitgevoerd op de database.
2. Ik heb de tijd 1 uur terug gezet.
3. Bovenstaande query nogmaals uitgevoerd.

Ik zie geen verschillen in de output, de tijden zijn onveranderd gebleven.

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 23-06 11:51

Janoz

Moderator Devschuur®

!litemod

Het zijn geen tijden. Het zijn lengtes van tijd. Die zullen inderdaad niet veranderen.

Je definieert de waarde als 'tijdsduur vanaf middernacht'. Wanneer je deze omzet naar een datum (dus optelt bij zondag 31 oktober 2010 0:00) dan zul je er een uur naast zitten.


Het is alsof je een plek bepaald middels een hoeveelheid meters. Dat werkt ook vanaf een referentiepunt. Wat je gedaan hebt is equivalent aan het opslaan van een afstand en het gebruiken als een positie.

[ Voor 45% gewijzigd door Janoz op 06-09-2010 15:13 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Janoz schreef op maandag 06 september 2010 @ 14:16:
Maar ja, als de klok terug gaat van 3 naar 2 dan zit je 8u na middernacht toch nog echt pas op 7:00am
Dat lijkt mij van niet, de TimeSpan kent geen tijdzone. DateTime kent wel de tijdzone. Zoals je zelf aangeeft bevat een TimeSpan in principe een tijdsduur. Het ingaan van de zomer- of winter tijd kan er natuurlijk wel voor zorgen dat bij de berekening waar de twee tijds momenten (datetime instances) om de tijdsduur te berekenen met verkeerd rekent..

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Janoz schreef op maandag 06 september 2010 @ 15:11:
Je definieert de waarde als 'tijdsduur vanaf middernacht'. Wanneer je deze omzet naar een datum (dus optelt bij zondag 31 oktober 2010 0:00) dan zul je er een uur naast zitten.
Dat begrijp ik, maar ik ga er nooit op die manier mee werken. Ik ga het überhaupt nooit bij datums optellen. Zoals MSDN ook al aangaf, ik gebruik het alleen als tijd indicatie en helemaal los van wat voor datum dan ook.

Heb je toevallig een alternatief voor het opslaan van alleen tijden? Ik kan er een varchar(5) van maken 00:00 maar daar zit ik eigenlijk helemaal niet op te wachten omdat het dan wel erg fout gevoelig is (34:56 zal gewoon opgeslagen kunnen worden).

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 27-06 12:22
Janoz schreef op maandag 06 september 2010 @ 14:16:
Maar ja, als de klok terug gaat van 3 naar 2 dan zit je 8u na middernacht toch nog echt pas op 7:00am
Een Timespan is gewoon een 'domme' rij bits met het aantal ticks (of aantal microseconden of zoiets). Het ligt dus puur aan je implementatie of je van dit probleem last hebt.

Als jij om middernacht (volgens de computerklok) van de database server ophaalt over hoeveel uur taak x moet gebeuren dan kun je het door jou beschreven probleem hebben. Als je de TimeSpan gewoon als een uur in een dag beschouwt dan heb je dit probleem helemaal niet :).

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 23-06 11:51

Janoz

Moderator Devschuur®

!litemod

Een String is ook een domme rij bits ;). Uiteraard ligt het aan je implementatie. Maar bij een tijdsspanne denk ik niet gelijk aan een tijdstip. Blijkbaar ben ik hierin de enige?

Maar goed. Hoe ik het zou doen weet ik niet. Ik doe nooit C#. In Java bestaat gewoon een Time object.
Niemand_Anders schreef op maandag 06 september 2010 @ 15:21:
[...]

Dat lijkt mij van niet, de TimeSpan kent geen tijdzone. DateTime kent wel de tijdzone. Zoals je zelf aangeeft bevat een TimeSpan in principe een tijdsduur. Het ingaan van de zomer- of winter tijd kan er natuurlijk wel voor zorgen dat bij de berekening waar de twee tijds momenten (datetime instances) om de tijdsduur te berekenen met verkeerd rekent..
Dat zeg ik toch ook? Ik heb het niet over tijdzone.

[ Voor 80% gewijzigd door Janoz op 06-09-2010 15:54 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • bastv
  • Registratie: September 2005
  • Laatst online: 23-06 10:03
kan je niet sql time datatype gebruiken?
http://msdn.microsoft.com/en-us/library/bb677243.aspx
je nhibernate mapping moet je dan ook aanpassen naar time
http://nhforge.org/blogs/...2-and-datetimeoffset.aspx

Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Thanks Bas! Ik heb de kolom in SQL Server al op Time(7) staan. De NHibernate mapping staat nu nog op TimeAsTimeSpan maar die zal ik morgen omzetten naar Time. Hopen dat dat werkt :)

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Janoz schreef op maandag 06 september 2010 @ 15:50:
Maar bij een tijdsspanne denk ik niet gelijk aan een tijdstip.
Nee ik ben het met je eens. Je zegt met een TimeSpan dat iets een x tijd na een ander iets is. Als je een timespan hebt met 8 uur, dan kan dat zoals je zelf al aangeeft inderdaad ook best op 7:00 of 9:00 vallen door winter/zomer tijd.

Ik vind het ook jammer dat er geen Date of Time structure in .NET is.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 27-06 12:22
Aan de andere kant:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct time
{

    //insert meerdere constructors met wat checks als minute < 60;
    //en natuurlijk wat properties om een en ander te veranderen en uit te lezen.
    private int hour, minute, second, millisecond;
    
    public overide bool Equals(object obj)
    {
        Time t = obj as Time;
        if (t == null) { return false; }

        return (t.hour == this.hour && t.minute == this.minute && t.second == this.second && t.millisecond == this.millisecond);
    }
    
    // <= en >= overloaden

    //etc..

    public string ToString()
    {
        return hour.ToString() + ": " + minute.ToString();
    }
}


Wat ook wel in de database te krijgen is (xmlserializer of als blob) hoewel dit misschien niet al te netjes is :).

[ Voor 17% gewijzigd door roy-t op 07-09-2010 10:27 ]

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
roy-t schreef op dinsdag 07 september 2010 @ 10:26:
Aan de andere kant:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct time
{

    //insert meerdere constructors met wat checks als minute < 60;
    //en natuurlijk wat properties om een en ander te veranderen en uit te lezen.
    private int hour, minute, second, millisecond;
    
    public overide bool Equals(object obj)
    {
        Time t = obj as Time;
        if (t == null) { return false; }

        return (t.hour == this.hour && t.minute == this.minute && t.second == this.second && t.millisecond == this.millisecond);
    }
    
    // <= en >= overloaden

    //etc..

    public string ToString()
    {
        return hour.ToString() + ": " + minute.ToString();
    }
}


Wat ook wel in de database te krijgen is (xmlserializer of als blob) hoewel dit misschien niet al te netjes is :).
Het is natuurlijk mogelijk. Je kunt met extension methods ook nog wel een SetTime/GetTime maken op DateTime, maar het zou mooi zijn als het gewoon in het framework opgenomen zou zijn, aangezien het toch een vrij voorkomend iets is.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Bedankt allemaal voor het mee denken! Het probleem heb ik net opgelost.

Wat heb ik gedaan?
- In de mapping file gebruik ik nu type="TimeSpan" i.p.v. type="TimeAsTimeSpan"
- In de database is de column nu gezet als bigint (Int64)

Werkt perfect :)

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Tony L schreef op dinsdag 07 september 2010 @ 11:16:
Bedankt allemaal voor het mee denken! Het probleem heb ik net opgelost.

Wat heb ik gedaan?
- In de mapping file gebruik ik nu type="TimeSpan" i.p.v. type="TimeAsTimeSpan"
- In de database is de column nu gezet als bigint (Int64)

Werkt perfect :)
Maar hoe reken je nu dan met TimeSpan's en DateTime's door elkaar? Dat kan potentieel foute resultaten opleveren.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Woy schreef op dinsdag 07 september 2010 @ 11:32:
[...]

Maar hoe reken je nu dan met TimeSpan's en DateTime's door elkaar? Dat kan potentieel foute resultaten opleveren.
Klopt maar ik reken niet met DateTime's :)
De tijd is alleen relevant voor mij, de datum totaal niet.

De TimeSpan zelf houdt alleen een interval bij, in dit geval resulteert dat in een Int64. Ik denk dat het probleem blijft bestaan ongeacht hoe je het opslaat. Pas wanneer je met DateTime's gaat rekenen komt het probleem naar voren en volgens mij maakt het daarom niet uit wat voor type je gebruikt aangezien de oorzaak de DateTime is, niet de manier van opslag. Stel dat je er een int van maakt 830 resulteert in 08:30. 2100 resulteert in 21:00. Dan blijf je hetzelfde probleem toch houden? Of zie ik wat over het hoofd?

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Tony L schreef op dinsdag 07 september 2010 @ 12:04:
[...]


Klopt maar ik reken niet met DateTime's :)
De tijd is alleen relevant voor mij, de datum totaal niet.

De TimeSpan zelf houdt alleen een interval bij, in dit geval resulteert dat in een Int64. Ik denk dat het probleem blijft bestaan ongeacht hoe je het opslaat. Pas wanneer je met DateTime's gaat rekenen komt het probleem naar voren en volgens mij maakt het daarom niet uit wat voor type je gebruikt aangezien de oorzaak de DateTime is, niet de manier van opslag. Stel dat je er een int van maakt 830 resulteert in 08:30. 2100 resulteert in 21:00. Dan blijf je hetzelfde probleem toch houden? Of zie ik wat over het hoofd?
Het probleem zit hem vooral in de betekenis, niet zozeer in de opslag. Een TimeSpan met 8 uur en 30 minuten heeft een andere betekenis dan de tijd 08:30.

Je kunt een TimeSpan best gebruiken om een Tijd in op te slaan, maar je kunt deze niet zomaar bij een datum met de tijd 00:00 optellen om op de juiste tijd te komen. Het probleem is dat je sowieso niet goed met een Tijd kunt rekenen, zonder dat je de context weet. 02:00 + 01:00 kan namelijk een verschillend resultaat opleveren afhankelijk van de datum en tijdzone.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Pagina: 1