www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - SysTime in a Struct

reply "albatroz" <rmcjustino gmail.com> writes:
Hi,

I have defined this struct
struct preEv {
     string edate; //010112
     string etime; //00:00:00
     string etext; //
     SysTime esystime;
     this (this) {
       SysTime esystime = SysTime(DateTime(
           Clock.currTime.year,
           to!int(this.edate[2..4]),
           to!int(this.edate[0..2]),
           to!int(etime[0..2]),
           to!int(etime[3..5]),
           to!int(etime[6..8])));
     }
}

If I write to the sctruct and then print it I'm able to see the
SysTime variable with a value.
writeln(preEv) //previousEvents("140212", "05:13:26", "9 140212
05:13:26 d", "2012-Feb-14 05:13:26")

but if trying to get the value from the SysTime variable I get a
Segmentation fault. Trying to read any other variable inside this
struct will not be a problem.

writeln (preEv.esystime.day) // will compile but segfaults

On DMD32 D Compiler v2.058

Any correct way to do this?

Thank you.
Mar 01 2012
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/01/2012 06:15 AM, albatroz wrote:
 Hi,

 I have defined this struct
 struct preEv {
 string edate; //010112
 string etime; //00:00:00
 string etext; //
 SysTime esystime;

That is a member of this type.
 this (this) {
 SysTime esystime = SysTime(DateTime(

That is a separate local variable within this(this). Also, this(this) is the postblit (similar to a copy constructor). Is that what you want to define? I think you want to simply do this anyway: esystime = or this: this.esystime =
 Clock.currTime.year,
 to!int(this.edate[2..4]),
 to!int(this.edate[0..2]),
 to!int(etime[0..2]),
 to!int(etime[3..5]),
 to!int(etime[6..8])));
 }
 }

 If I write to the sctruct and then print it I'm able to see the
 SysTime variable with a value.
 writeln(preEv) //previousEvents("140212", "05:13:26", "9 140212
 05:13:26 d", "2012-Feb-14 05:13:26")

 but if trying to get the value from the SysTime variable I get a
 Segmentation fault.

Probably because esystime member is no initialized.
 Trying to read any other variable inside this
 struct will not be a problem.

 writeln (preEv.esystime.day) // will compile but segfaults

 On DMD32 D Compiler v2.058

 Any correct way to do this?

 Thank you.

Ali
Mar 01 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/01/2012 09:14 AM, albatroz wrote:
 Have fixed the segfault by using DateTime instead of SysTime.
 That is a separate local variable within this(this). Also, this(this)
 is the postblit (similar to a copy constructor). Is that what you want
 to define?

No, but not using this(this) will fail to build with: static variable _initialized cannot be read at compile time

So you are trying to initialize the member with a default initializer, like this: struct prevEv { // ... DateTime edatetime = DateTime(/* ... */); } For that to work, the initial value must be a compile-time value. I am not sure that you want that. Also, this(this) is needed in very rare cases. Are you trying to create objects of prevEv? Then you should use this(). Unfortunately, structs cannot have default constructors. A solution might be to use a function that makes and returns a prevEv: prevEv make_prevEv() { return prevEv(/* ... */, DateTime(/* ... */)); }
 Making the struct similar to what you suggest will work.
 struct prevEv {
 string edate;
 string etime;
 string etext;
 DateTime edatetime;
 this (this)
 {
 edatetime = DateTime(
 Clock.currTime.year,
 to!int(this.edate[2..4]),
 to!int(this.edate[0..2]),
 to!int(etime[0..2]),
 to!int(etime[3..5]),
 to!int(etime[6..8]));
 }
 }

 Just not has expected, do you have any suggestion how to do it properly?

Are you trying to record the time when a prevEv is copied from another one? If not, I suggest not defining this(this). It is the postblit, to make things right for rare structs and only when the compiler generated copying is wrong for a that type. Or, are you just trying to define a type that contains time information?
 writeln ( prevEv.edatetime ); //0001-Jan-01 00:00:00
 writeln ( prevEv ); // preEv("140212", "05:13:26", "9 140212 05:13:26
 d", 2012-Feb-14 05:13:26)

 Ali


Ali
Mar 01 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/01/2012 03:46 PM, albatroz wrote:

 Hi Ali, just tring to define a type that holds this information. It was
 just an attempt to create a type DateTime with the values from the known
 strings, I thought it was possible to create the definition directly in
 the Struct, with no need for an external function.
 edate and etime are strings that I will read in to the struct, but for
 operations with time and dates I need to create/define a DateTime type.

From that description, it looks like you can hold edate etc. as members and produce SysTime as needed. The following demonstrates how to convert preEv to SysTime by opCast implicitly and by sys_time explicitly: import std.stdio; import std.conv; import std.datetime; struct preEv { string edate; //010112 string etime; //00:00:00 string etext; // SysTime opCast(T : SysTime)() const { return SysTime(DateTime( Clock.currTime.year, to!int(this.edate[2..4]), to!int(this.edate[0..2]), to!int(etime[0..2]), to!int(etime[3..5]), to!int(etime[6..8]))); } SysTime sys_time() const property { return to!SysTime(this); } } void main() { auto pe = preEv("010312", "15:53:00", "The event"); // Explicit conversion auto st0 = to!SysTime(pe); writeln(st0); // Casting auto st1 = cast(SysTime)(pe); writeln(st1); // As a property auto st2 = pe.sys_time; writeln(st2); } If you think that you need to cache SysTime in the object itself, you can do that for example in opCast. On the other hand, if all you need to store is SysTime and etext, then you need to create SysTime in the constructor: import std.stdio; import std.conv; import std.datetime; struct preEv { SysTime time; string etext; this (string edate, string etime, string etext) { this.time = SysTime(DateTime( Clock.currTime.year, to!int(edate[2..4]), to!int(edate[0..2]), to!int(etime[0..2]), to!int(etime[3..5]), to!int(etime[6..8]))); this.etext = etext; } } void main() { auto pe = preEv("010312", "15:53:00", "The event"); writeln(pe.time); } Ali
Mar 01 2012
prev sibling next sibling parent "albatroz" <rmcjustino gmail.com> writes:
Have fixed the segfault by using DateTime instead of SysTime.
 That is a separate local variable within this(this). Also, 
 this(this) is the postblit (similar to a copy constructor). Is 
 that what you want to define?

No, but not using this(this) will fail to build with: static variable _initialized cannot be read at compile time Making the struct similar to what you suggest will work. struct prevEv { string edate; string etime; string etext; DateTime edatetime; this (this) { edatetime = DateTime( Clock.currTime.year, to!int(this.edate[2..4]), to!int(this.edate[0..2]), to!int(etime[0..2]), to!int(etime[3..5]), to!int(etime[6..8])); } } Just not has expected, do you have any suggestion how to do it properly? writeln ( prevEv.edatetime ); //0001-Jan-01 00:00:00 writeln ( prevEv ); // preEv("140212", "05:13:26", "9 140212 05:13:26 d", 2012-Feb-14 05:13:26)
 Ali

Mar 01 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, March 01, 2012 15:15:00 albatroz wrote:
 Hi,
 
 I have defined this struct
 struct preEv {
 string edate; //010112
 string etime; //00:00:00
 string etext; //
 SysTime esystime;
 this (this) {
 SysTime esystime = SysTime(DateTime(
 Clock.currTime.year,
 to!int(this.edate[2..4]),
 to!int(this.edate[0..2]),
 to!int(etime[0..2]),
 to!int(etime[3..5]),
 to!int(etime[6..8])));
 }
 }
 
 If I write to the sctruct and then print it I'm able to see the
 SysTime variable with a value.
 writeln(preEv) //previousEvents("140212", "05:13:26", "9 140212
 05:13:26 d", "2012-Feb-14 05:13:26")
 
 but if trying to get the value from the SysTime variable I get a
 Segmentation fault. Trying to read any other variable inside this
 struct will not be a problem.
 
 writeln (preEv.esystime.day) // will compile but segfaults
 
 On DMD32 D Compiler v2.058
 
 Any correct way to do this?

A default-initialized SysTime is useless. It hasn't been properly initialized. SysTime contains a time zone object, which is a class and must be initialized at runtime (so directly initializing it won't work), and that object is null in SysTime.init (and it can't be anything else, because you can't construct a class at compile and have it persist to runtime). You need to actually initialize a SysTime before using it. So, using the init value of struct which has a SysTime as a member probably isn't a great idea. - Jonathan M Davis
Mar 01 2012
prev sibling next sibling parent "albatroz" <rmcjustino gmail.com> writes:
 Are you trying to record the time when a prevEv is copied from 
 another one? If not, I suggest not defining this(this). It is 
 the postblit, to make things right for rare structs and only 
 when the compiler generated copying is wrong for a that type.

 Or, are you just trying to define a type that contains time 
 information?

Hi Ali, just tring to define a type that holds this information. It was just an attempt to create a type DateTime with the values from the known strings, I thought it was possible to create the definition directly in the Struct, with no need for an external function. edate and etime are strings that I will read in to the struct, but for operations with time and dates I need to create/define a DateTime type. Thanks
Mar 01 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, March 01, 2012 16:00:09 Ali Çehreli wrote:
 On 03/01/2012 03:46 PM, albatroz wrote:
 Hi Ali, just tring to define a type that holds this information. It was
 just an attempt to create a type DateTime with the values from the known
 strings, I thought it was possible to create the definition directly in
 the Struct, with no need for an external function.
 edate and etime are strings that I will read in to the struct, but for
 operations with time and dates I need to create/define a DateTime type.

From that description, it looks like you can hold edate etc. as members and produce SysTime as needed. The following demonstrates how to convert preEv to SysTime by opCast implicitly and by sys_time explicitly: import std.stdio; import std.conv; import std.datetime; struct preEv { string edate; //010112 string etime; //00:00:00 string etext; // SysTime opCast(T : SysTime)() const { return SysTime(DateTime( Clock.currTime.year, to!int(this.edate[2..4]), to!int(this.edate[0..2]), to!int(etime[0..2]), to!int(etime[3..5]), to!int(etime[6..8]))); } SysTime sys_time() const property { return to!SysTime(this); } } void main() { auto pe = preEv("010312", "15:53:00", "The event"); // Explicit conversion auto st0 = to!SysTime(pe); writeln(st0); // Casting auto st1 = cast(SysTime)(pe); writeln(st1); // As a property auto st2 = pe.sys_time; writeln(st2); } If you think that you need to cache SysTime in the object itself, you can do that for example in opCast. On the other hand, if all you need to store is SysTime and etext, then you need to create SysTime in the constructor: import std.stdio; import std.conv; import std.datetime; struct preEv { SysTime time; string etext; this (string edate, string etime, string etext) { this.time = SysTime(DateTime( Clock.currTime.year, to!int(edate[2..4]), to!int(edate[0..2]), to!int(etime[0..2]), to!int(etime[3..5]), to!int(etime[6..8]))); this.etext = etext; } } void main() { auto pe = preEv("010312", "15:53:00", "The event"); writeln(pe.time); }

You know, you can create a TimeOfDay from "15:53:00" with TimeOfDay.fromISOExtString. That won't work with the date, since it's not in either the ISO or ISO Extended format, but it would work for the time. I'd also point out that currTime isn't a property (since it takes an optional TimeZone argument), so you really should be using parens when you call it. Otherwise, once property enforcement is enabled, your code won't compile. Also, you should use std.conv.to, not a cast, when converting, since std.conv.to now supports calling user-defined opCasts, and there's less risk of screwing up the cast if you use std.conv.to. So, defining an opCast is fine, but it should probably be used with std.conv.to rather than directly. - Jonathan M Davis
Mar 01 2012
prev sibling parent "albatroz" <rmcjustino gmail.com> writes:
Hi Ali,

only today I had the time to implement your suggestion it's 
working now has expected.

Thank you for your patience, also thank you for the work 
translating such a good D book to English.


On Friday, 2 March 2012 at 00:00:10 UTC, Ali Çehreli wrote:
 On 03/01/2012 03:46 PM, albatroz wrote:

 Hi Ali, just tring to define a type that holds this

 just an attempt to create a type DateTime with the values

 strings, I thought it was possible to create the definition

 the Struct, with no need for an external function.
 edate and etime are strings that I will read in to the

 operations with time and dates I need to create/define a

From that description, it looks like you can hold edate etc. as members and produce SysTime as needed. The following demonstrates how to convert preEv to SysTime by opCast implicitly and by sys_time explicitly: import std.stdio; import std.conv; import std.datetime; struct preEv { string edate; //010112 string etime; //00:00:00 string etext; // SysTime opCast(T : SysTime)() const { return SysTime(DateTime( Clock.currTime.year, to!int(this.edate[2..4]), to!int(this.edate[0..2]), to!int(etime[0..2]), to!int(etime[3..5]), to!int(etime[6..8]))); } SysTime sys_time() const property { return to!SysTime(this); } } void main() { auto pe = preEv("010312", "15:53:00", "The event"); // Explicit conversion auto st0 = to!SysTime(pe); writeln(st0); // Casting auto st1 = cast(SysTime)(pe); writeln(st1); // As a property auto st2 = pe.sys_time; writeln(st2); } If you think that you need to cache SysTime in the object itself, you can do that for example in opCast. On the other hand, if all you need to store is SysTime and etext, then you need to create SysTime in the constructor: import std.stdio; import std.conv; import std.datetime; struct preEv { SysTime time; string etext; this (string edate, string etime, string etext) { this.time = SysTime(DateTime( Clock.currTime.year, to!int(edate[2..4]), to!int(edate[0..2]), to!int(etime[0..2]), to!int(etime[3..5]), to!int(etime[6..8]))); this.etext = etext; } } void main() { auto pe = preEv("010312", "15:53:00", "The event"); writeln(pe.time); } Ali

Mar 06 2012