View mode: basic / threaded / horizontal-split · Log in · Help
March 01, 2012
SysTime in a Struct
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.
March 01, 2012
Re: SysTime in a Struct
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
March 01, 2012
Re: SysTime in a Struct
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
Thanks
March 01, 2012
Re: SysTime in a Struct
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
> Thanks
>

Ali
March 01, 2012
Re: SysTime in a Struct
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
March 01, 2012
Re: SysTime in a Struct
> 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
March 02, 2012
Re: SysTime in a Struct
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
March 02, 2012
Re: SysTime in a Struct
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
March 06, 2012
Re: SysTime in a Struct
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
> 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
Top | Discussion index | About this forum | D home