How do I convert a time to tm struct instead of CTime class - time-t

I currently have code that creates a CTime object from a defined value.
#define TIME_VALUE 0x301DDF00 // Aug 1, 1995 # 04:00:00
CTime t = CTime( TIME_VALUE );
This creates the desired date of Aug 1, 1995 04:00:00
I can no longer use CTime so I am trying to use time_t and tm instead. Since the CTime constructor takes in the number of seconds since Jan 1, 1970 and time_t represents the number of seconds since Jan 1, 1970, I tried to use the following code.
#define TIME_VALUE 0x301DDF00 // Aug 1, 1995 # 04:00:00
time_t tmpTime = TIME_VALUE;
struct tm createTime;
if( localtime_s( &createTime, &tmpTime ) == S_OK )
{
// Use createTime
}
createTime ends up as August 1, 0095 04:00:00. How am I supposed to go from the defined value to a time_t and tm successfully?
Thanks in advance.

Sorry. I didn't look at the tm documentation closely enough. The year is the actual year minus 1900 and the month is zero based. I got it now.

Related

What is this time format? (10 digits, 5 decimals)

So a website that I'm using has a websocket and they provide the broadcast time in the following manner:
"broadcasted_at":1574325570.71308
What is this time format and how do they generate it?
Unix epoch time ... the number of seconds that have elapsed since the Unix epoch, that is the time 00:00:00 UTC on 1 January 1970
now : 1574327074 : Thu Nov 21 03:04:34 2019
start of day : 1574316000 : Thu Nov 21 00:00:00 2019
1574325570 : 1574325570 : Thu Nov 21 02:39:30 2019
convert online : https://www.epochconverter.com/
... or download code (to build) to have command line program to perform the conversion https://github.com/darrenjs/c_dev_utils
I'm guessing the fractional part is the number of microseconds within the current second.
… and how do they generate it?
I don’t know, of course, what language or libraries your website is using. So this is just an example. To generate a value like 1574325570.71308 in Java:
Instant now = Instant.now();
double epochSeconds = now.getEpochSecond()
+ (double) now.getNano() / (double) TimeUnit.SECONDS.toNanos(1);
String result = String.format(Locale.ROOT, "%f", epochSeconds);
System.out.println("result: " + result);
When I ran this snippet just now (2019-12-15T11:18:01.562699Z), the output was:
result: 1576408681.562699
If you want exactly 5 decimals always another way is to use a DateTimeFormatter:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.INSTANT_SECONDS)
.appendPattern(".SSSSS")
.toFormatter();
String result = formatter.format(now);
result: 1576408681.56269

Get UTC offset for Timezone at given date via Ruby/tzinfo?

This is probably trivial for anybody who knows the tzinfo API:
Given a Timezone object from tzinfo, how can I get the UTC offset at a given point in time (given either in local time of the Timezone or UTC)?
You can use the period_for_local method. For these examples, I'm using the timezone I live in (America/Sao_Paulo), in where the offset is -03:00 during winter (March to October) and -02:00 during summer (Daylight Saving Time):
# Sao Paulo timezone
zone = TZInfo::Timezone.new('America/Sao_Paulo')
# date in January (Brazilia Summer Time - DST)
d = DateTime.new(2017, 1, 1, 10, 0)
period = zone.period_for_local(d)
puts period.offset.utc_total_offset / 3600.0
# date in July (Brazilia Standard Time - not in DST)
d = DateTime.new(2017, 7, 1, 10, 0)
period = zone.period_for_local(d)
puts period.offset.utc_total_offset / 3600.0
The output is:
-2.0
-3.0
The utc_total_offset method returns the offset in seconds, so I divided by 3600 to get the value in hours.
Note that I also used 3600.0 to force the results to be a float. If I just use 3600, the results will be rounded and timezones like Asia/Kolkata (which has an offset of +05:30) will give incorrect results (5 instead of 5.5).
Note that you must be aware of DST changes, because you can have either a gap or a overlap.
In São Paulo timezone, DST starts at October 15th 2017: at midnight, clocks shift forward to 1 AM (and offset changes from -03:00 to -02:00), so all the local times between 00:00 and 01:00 are not valid. In this case, if you try to get the offset, it will get a PeriodNotFound error:
# DST starts at October 15th, clocks shift from midnight to 1 AM
d = DateTime.new(2017, 10, 15, 0, 30)
period = zone.period_for_local(d) # error: TZInfo::PeriodNotFound
When DST ends, at February 18th 2018, at midnight clocks shift back to 11 PM of 17th (and offset changes from -02:00 to -03:00), so the local times between 11 PM and midnight exist twice (in both offsets).
In this case, you must specify which one you want (by setting the second parameter of period_for_local), indicating if you want the offset for DST or not:
# DST ends at February 18th, clocks shift from midnight to 11 PM of 17th
d = DateTime.new(2018, 2, 17, 23, 30)
period = zone.period_for_local(d, true) # get DST offset
puts period.offset.utc_total_offset / 3600.0 # -2.0
period = zone.period_for_local(d, false) # get non-DST offset
puts period.offset.utc_total_offset / 3600.0 # -3.0
If you don't specify the second parameter, you'll get a TZInfo::AmbiguousTime error:
# error: TZInfo::AmbiguousTime (local time exists twice due do DST overlap)
period = zone.period_for_local(d)
It seems in Ruby 1.9.3 there is some hackery (DateTime to Time) involved, with possible loss of precision, but this is my result based on the answer from #Hugo:
module TZInfo
class Timezone
def utc_to_local_zone(dateTime)
return dateTime.to_time.getlocal(self.period_for_utc(dateTime).utc_total_offset)
end
def offset_to_s(dateTime, format = "%z")
return utc_to_local_zone(dateTime).strftime(format)
end
end
end

How to format current time using a yyyyMMddHHmmss format?

I'm trying to format the current time using this format yyyyMMddHHmmss.
t := time.Now()
fmt.Println(t.Format("yyyyMMddHHmmss"))
That is outputting:
yyyyMMddHHmmss
Any suggestions?
Use
fmt.Println(t.Format("20060102150405"))
as Go uses following constants to format date,refer here
const (
stdLongMonth = "January"
stdMonth = "Jan"
stdNumMonth = "1"
stdZeroMonth = "01"
stdLongWeekDay = "Monday"
stdWeekDay = "Mon"
stdDay = "2"
stdUnderDay = "_2"
stdZeroDay = "02"
stdHour = "15"
stdHour12 = "3"
stdZeroHour12 = "03"
stdMinute = "4"
stdZeroMinute = "04"
stdSecond = "5"
stdZeroSecond = "05"
stdLongYear = "2006"
stdYear = "06"
stdPM = "PM"
stdpm = "pm"
stdTZ = "MST"
stdISO8601TZ = "Z0700" // prints Z for UTC
stdISO8601ColonTZ = "Z07:00" // prints Z for UTC
stdNumTZ = "-0700" // always numeric
stdNumShortTZ = "-07" // always numeric
stdNumColonTZ = "-07:00" // always numeric
stdFracSecond0 = ".0", ".00" // trailing zeros included
stdFracSecond9 = ".9", ".99" // trailing zeros omitted
)
This question comes in top of Google search when you find "golang current time format" so, for all the people that want to use another format, remember that you can always call to:
t := time.Now()
t.Year()
t.Month()
t.Day()
t.Hour()
t.Minute()
t.Second()
For example, to get current date time as "YYYY-MM-DDTHH:MM:SS" (for example 2019-01-22T12:40:55) you can use these methods with fmt.Sprintf:
t := time.Now()
formatted := fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02d",
t.Year(), t.Month(), t.Day(),
t.Hour(), t.Minute(), t.Second())
As always, remember that docs are the best source of learning: https://golang.org/pkg/time/
Option 1: Go standard library
t.Format("20060102150405")
Unit
Golang Layout
Examples
Note
Year
06
21, 81, 01
Year
2006
2021, 1981, 0001
Month
January
January, February, December
Month
Jan
Jan, Feb, Dec
Month
1
1, 2, 12
Month
01
01, 02, 12
Day
Monday
Monday, Wednesday, Sunday
Day
Mon
Mon, Wed, Sun
Day
2
1, 2, 11, 31
Day
02
01, 02, 11, 31
zero padded day of the month
Day
_2
⎵1, ⎵2, 11, 31
space padded day of the month
Day
002
001, 002, 011, 031, 145, 365, 366
zero padded day of the year
Day
__2
⎵⎵1, ⎵⎵2, ⎵11, ⎵31, 365, 366
space padded day of the year
Part of day
PM
AM, PM
Part of day
pm
am, pm
Hour 24h
15
00, 01, 12, 23
Hour 12h
3
1, 2, 12
Hour 12h
03
01, 02, 12
Minute
4
0, 4 ,10, 35
Minute
04
00, 04 ,10, 35
Second
5
0, 5, 25
Second
05
00, 05, 25
10-1 to 10-9 s
.0 .000000000
.1, .199000000
Trailing zeros included
10-1 to 10-9 s
.9 .999999999
.1, .199
Trailing zeros omitted
Time zone
MST
UTC, MST, CET
Time zone
Z07
Z, +08, -05
Z is for UTC
Time zone
Z0700
Z, +0800, -0500
Z is for UTC
Time zone
Z070000
Z, +080000, -050000
Z is for UTC
Time zone
Z07:00
Z, +08:00, -05:00
Z is for UTC
Time zone
Z07:00:00
Z, +08:00:00, -05:00:00
Z is for UTC
Time zone
-07
+00, +08, -05
Time zone
-0700
+0000, +0800, -0500
Time zone
-070000
+000000, +080000, -050000
Time zone
-07:00
+00:00, +08:00, -05:00
Time zone
-07:00:00
+00:00:00, +08:00:00, -05:00:00
In Golang 1.17+ for fraction of seconds (.999 or .000) you can use , instead of . (,999 or ,000) but output is always with .!!! See https://github.com/golang/go/issues/48037
Option 2: strftime Go implementation
import strftime "github.com/itchyny/timefmt-go"
strftime.Format(t, "%Y%m%d%H%M%S")
See for more info
https://github.com/itchyny/timefmt-go
https://linux.die.net/man/3/strftime
import("time")
layout := "2006-01-02T15:04:05.000Z"
str := "2014-11-12T11:45:26.371Z"
t, err := time.Parse(layout, str)
if err != nil {
fmt.Println(err)
}
fmt.Println(t)
gives:
>> 2014-11-12 11:45:26.371 +0000 UTC
Time package in Golang has some methods that might be worth looking.
func (Time) Format
func (t Time) Format(layout string) string
Format returns a textual representation of the time value formatted according to layout, which defines the format by showing how the reference time,
Mon Jan 2 15:04:05 -0700 MST 2006
would be displayed if it were the value; it serves as an example of the desired output. The same display rules will then be applied to the time value. Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard and convenient representations of the reference time. For more information about the formats and the definition of the reference time, see the documentation for ANSIC and the other constants defined by this package.
Source (http://golang.org/pkg/time/#Time.Format)
I also found an example of defining the layout (http://golang.org/src/pkg/time/example_test.go)
func ExampleTime_Format() {
// layout shows by example how the reference time should be represented.
const layout = "Jan 2, 2006 at 3:04pm (MST)"
t := time.Date(2009, time.November, 10, 15, 0, 0, 0, time.Local)
fmt.Println(t.Format(layout))
fmt.Println(t.UTC().Format(layout))
// Output:
// Nov 10, 2009 at 3:00pm (PST)
// Nov 10, 2009 at 11:00pm (UTC)
}
Go standard library: time
now := time.Now()
fmt.Println(now) // 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
fmt.Println(now.Format("20060102150405"))
fmt.Println(now.Format("2006/01/02/15/04/05"))
fmt.Println(now.Format("2006-01-02 15:04:05"))
fmt.Println(now.Format("2006-01-02 15:04"))
fmt.Println(now.Format("2006/01/02 15:04:05"))
fmt.Println(now.Format("2006/01/02 15:04:05 (-0700)"))
fmt.Println(now.Format("2006年01月02日 15:04"))
fmt.Println(now.Format(time.Layout)) // 01/02 03:04:05PM '06 -0700
fmt.Println(now.Format(time.ANSIC)) // Mon Jan _2 15:04:05 2006
fmt.Println(now.Format(time.UnixDate)) // Mon Jan _2 15:04:05 MST 2006
fmt.Println(now.Format(time.RubyDate)) // Mon Jan 02 15:04:05 -0700 2006
fmt.Println(now.Format(time.RFC822)) // 02 Jan 06 15:04 MST
fmt.Println(now.Format(time.RFC850)) // Monday, 02-Jan-06 15:04:05 MST
fmt.Println(now.Format(time.Kitchen)) // 3:04PM
fmt.Println(now.Format(time.Stamp)) // Jan _2 15:04:05
Go playground

Find the specific day of a given month and given year

is there a Perl module which could give me for input month and year, let say, 06-2005, what the last day of this month for this year is? For this example, it is easy, because June always has 30 days, so the last day will be 30-06-2005. But it is not the case for February. So, if I have 02-1997, I would like to know whether to return 28-02-1997 or 29-02-1997. Thanks in advance.
Yes, there is a subroutine Days_in_Month in the Date::Calc module.
use strict;
use warnings;
use Date::Calc qw/Days_in_Month/;
for my $m (1 .. 12) {
print Days_in_Month(2005, $m), "\n";
}
OUTPUT
31
28
31
30
31
30
31
31
30
31
30
31
The last day in a given month is the "0th" day of the following month. mktime() takes a 0-based month and 1900-based year number, and returns an epoch timestamp.
use POSIX qw( mktime strftime );
sub last_day {
my ( $year, $mon ) = #_;
return mktime(0,0,0, 0, $mon, $year-1900);
}
You can pass that to localtime or strftime.
say scalar localtime last_day(2005, 5)
'Tue May 31 00:00:00 2005'
say scalar localtime last_day(2005, 6)
'Thu Jun 30 00:00:00 2005'
say scalar localtime last_day(1997, 2)
'Fri Feb 28 00:00:00 1997'
say scalar localtime last_day(2012, 2)
'Wed Feb 29 00:00:00 2012'
say (localtime last_day(1997, 2))[3]
'28'
say strftime "%d", localtime last_day(1997, 2)
'28'
As others said, use DateTime:
use DateTime;
my $dt = DateTime->last_day_of_month('year'=>2000, 'month'=>2);
print $dt->ymd; # '2000-02-29'
While DateTime may not be the fastest module for handling dates/times, it's definitely the most complete one. It's also the only one that handles the various quirks of date/time math correctly.

Mac dayofweek issue

Would anyone know why the following code works correctly on Windows and not on Mac??
Today (24/11/2010) should return 47 not 48 as per MacOS
def fm_date = '24/11/2010'
import java.text.SimpleDateFormat
def lPad = {it ->
st = '00' + it.toString()
return st.substring(st.length()-2, st.length())
}
dfm = new SimpleDateFormat("dd/MM/yyyy")
cal=Calendar.getInstance()
cal.setTime( dfm.parse(fm_date) )
now = cal.get(Calendar.WEEK_OF_YEAR)
cal.add(Calendar.DAY_OF_MONTH,-7)
prev = cal.get(Calendar.WEEK_OF_YEAR)
cal.add(Calendar.DAY_OF_MONTH,14)
next = cal.get(Calendar.WEEK_OF_YEAR)
prev = 'diary' + lPad(prev) + '.shtml'
next = 'diary' + lPad(next) + '.shtml'
return 'diary' + lPad(now) + '.shtml'
I believe it's an ISO week number issue...
If I use this code adapted (and groovyfied) from yours:
import java.text.SimpleDateFormat
def fm_date = '24/11/2010'
Calendar.getInstance().with { cal ->
// We want ISO Week numbers
cal.firstDayOfWeek = MONDAY
cal.minimalDaysInFirstWeek = 4
setTime new SimpleDateFormat( 'dd/MM/yyyy' ).parse( fm_date )
now = cal[ WEEK_OF_YEAR ]
}
"diary${"$now".padLeft( 2, '0' )}.shtml"
I get diary47.shtml returned
As the documentation for GregorianCalendar explains, if you want ISO Month numbers:
Values calculated for the WEEK_OF_YEAR
field range from 1 to 53. Week 1 for a
year is the earliest seven day period
starting on getFirstDayOfWeek() that
contains at least
getMinimalDaysInFirstWeek() days from
that year. It thus depends on the
values of getMinimalDaysInFirstWeek(),
getFirstDayOfWeek(), and the day of
the week of January 1. Weeks between
week 1 of one year and week 1 of the
following year are numbered
sequentially from 2 to 52 or 53 (as
needed).
For example, January 1, 1998 was a
Thursday. If getFirstDayOfWeek() is
MONDAY and getMinimalDaysInFirstWeek()
is 4 (these are the values reflecting
ISO 8601 and many national standards),
then week 1 of 1998 starts on December
29, 1997, and ends on January 4, 1998.
If, however, getFirstDayOfWeek() is
SUNDAY, then week 1 of 1998 starts on
January 4, 1998, and ends on January
10, 1998; the first three days of 1998
then are part of week 53 of 1997.
Edit
Even Groovier (from John's comment)
def fm_date = '24/11/2010'
Calendar.getInstance().with { cal ->
// We want ISO Week numbers
cal.firstDayOfWeek = MONDAY
cal.minimalDaysInFirstWeek = 4
cal.time = Date.parse( 'dd/MM/yyyy', fm_date )
now = cal[ WEEK_OF_YEAR ]
}
"diary${"$now".padLeft( 2, '0' )}.shtml"
Edit2
Just ran this on Windows using VirtualBox, and got the same result

Resources